Dans l'architecture de microservice, nous avons divisé un projet en de nombreux modules indépendants, qui fonctionnent ensemble via des appels distants. Cependant, dans le cas d'une concurrence élevée, l'augmentation du nombre de communications entraînera une augmentation du temps de communication total. Dans le même temps, les ressources du pool de threads sont également limitées. Un environnement de concurrence élevé entraînera un grand nombre de threads dans un état d'attente, ce qui entraînera des retards de réponse. Afin de résoudre ces problèmes, nous devons comprendre la fusion de la demande d'Hystrix.
Les demandes de fusion dans Hystrix consiste à utiliser un processeur de fusion pour fusionner les demandes consécutives initiées par le même service en une seule demande de traitement (la fenêtre temporelle de ces demandes continues est de 10 ms par défaut). L'une des classes de base impliquées dans ce processus est HystrixCollapser, OK. Ensuite, examinons comment implémenter la fusion de la demande Hystrix.
Interface du fournisseur de services
J'ai besoin de fournir deux interfaces dans le fournisseur de services pour les consommateurs de services, comme suit:
@RequestMapping ("/ getBook6") Liste publique <Book> Book6 (String IDS) { System.out.println ("ids >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 33, "Hu Shi", "Aucun")); Maison de publication de littérature 2 "); livre de retour;}La première interface est une interface par lots et la deuxième interface est une interface qui gère une seule demande. Dans l'interface lot, le format de paramètre IDS envoyé par le consommateur de service est 1, 2, 3, 4 ... ce format. Dans des circonstances normales, nous devons interroger les données correspondantes en fonction des IDS, puis l'assembler dans un ensemble à retourner. Par souci de traitement facile, je retournerai le même ensemble de données quel que soit le type de demande; L'interface pour le traitement d'une seule demande est relativement simple, donc je ne le répéterai pas.
Serviant les consommateurs
OK, une fois que le fournisseur de services l'a géré, jetons un coup d'œil à la façon dont les consommateurs de services devraient le gérer.
Bookservice
Tout d'abord, ajoutez deux méthodes au BookService pour appeler l'interface fournie par le fournisseur de services, comme suit:
Public Book Test8 (Long ID) {return restTEmplate.getForObject ("http: // hello-service / getBook6 / {1}", book.class, id);} public list <Book> test9 (list <long> ids) {System.out.println ("test9 -------" + ids + "thread.currentThread (). Thread.currentThread (). GetName ()); Book [] books = restTemplate.getForObject ("http: // bonjour-service / getBook6? Ids = {1}", livre []. Class, stringUtils.join (ids, ",")); return arrays.aslist (livres);}Test8 est utilisé pour appeler l'interface qui fournit un seul ID, Test9 est utilisé pour appeler l'interface ce traitement par lots. Dans Test9, j'imprime le fil où Test9 est exécuté pour nous faciliter pour observer les résultats d'exécution. De plus, dans Restemplate, si la valeur de retour est une collection, nous devons la recevoir d'abord avec un tableau, puis la convertir en collection (peut-être qu'il existe d'autres méthodes, les amis ont de meilleures suggestions à faire).
Bookbatchcommand
OK, une fois que la méthode de BookService est prête, nous pouvons créer un bookbatchcommand, qui est une commande par lots, comme suit:
classe publique BookBatchCommand étend HystrixCommand <list <Book>> {private list <long> ids; BookService Private BookService; Public BookBatchCommand (list <long> ids, bookservice bookservice) {super (seter.withgroupkey (HystrixCommandgroupkey.factory.askey ("CollapsingGroup"))) .AndCommandKey (HystrixCommandkey.factory.Askey ("CollapSingKey"))); this.ids = ids; this.bookservice = bookservice; } @Override Protected List <Book> run () lève une exception {return bookservice.test9 (ids); }}Cette classe est en fait similaire à la classe que nous avons introduite dans le blog précédent. Ils sont tous deux hérités de HystrixCommand et sont utilisés pour gérer les demandes fusionnées et appeler la méthode Test9 dans BookService dans la méthode d'exécution.
BookCollapsecommand
Ensuite, nous devons créer BookCollapsCommand hérité de HystrixCollapser pour implémenter la demande de demande. comme suit:
classe publique BookCollapsCommand étend HystrixCollapseer <list <book>, livre, long> {private bookservice bookservice; ID long privé; Public BookCollapSecommand (BookService BookService, long id) {super (seter.withcollapserkey (HystrixCollapserkey.factory.askey ("bookCollapSecommand")). etCollapserPropertiesDefauts (HystrixCollapSerproperties.Setter (). this.bookservice = bookservice; this.id = id; } @Override public long getRequestargument () {return id; } @Override Protected HystrixCommand <list <book>> createCommand (Collection <CollapSeDequest <Book, Long >> CollapSeDequests) {list <long> ids = new ArrayList <> (effondrementdrequestS.Size ()); ids.Addall (EncalcapSeDrequests.Stream (). Map (EncalcSeDrequest :: getargument) .Collect (collectionners.tolist ())); BookBatchCommand bookBatchCommand = new BookBatchCommand (ids, bookservice); return bookBatchCommand; } @Override Protected void MapResponSetOrequests (List <Book> BatchResponse, Collection <CollapSeDequest <Book, Long >> CollapSeDrequests) {System.out.println ("MapResponSetOrequests"); int count = 0; pour (EfforcedReDequest <book, long> effondrementDedrequest: effondrementDequests) {book book = batchResponse.get (count ++); ECHAPSEDREQUEST.SetResponse (livre); }}}En ce qui concerne cette classe, je dirai les points suivants:
1. Tout d'abord, dans la méthode de construction, nous définissons la fenêtre de temps de demande sur 100 ms, c'est-à-dire que les demandes avec l'intervalle de temps de demande à moins de 100 ms seront fusionnées en une seule demande.
2. La méthode CreateCommand est principalement utilisée pour fusionner les demandes, obtenir les ID de chaque demande ici, mettre ces ID unique dans une collection, puis créer un objet BookBatchCommand et utiliser cet objet pour initier une demande de lot.
3. La méthode MapResponSetorequests est principalement utilisée pour définir le résultat de la demande pour chaque demande. Le premier paramètre de cette méthode représente le résultat de la demande de lots, et le deuxième paramètre EffondrementDequests représente chaque demande fusionnée. Ensuite, nous définissons le résultat de la demande pour CollapSeDrequests en traversant BatchResponse.
OK, une fois toutes ces opérations terminées, nous pouvons venir la tester.
test
Nous créons une interface d'accès du côté consommateur du service pour tester la demande de fusion. L'interface de test est la suivante:
@RequestMapping ("/ test7") @ réponsebodypublic void test7 () lève ExecutionException, interruptedException {HystrixRequestContext context = HystrixRequestContext.InitializEContext (); BookCollapSecommand BC1 = new BookCollapSecommand (BookService, 1L); BookCollapSecommand BC2 = new BookCollapSecommand (BookService, 2L); BookCollapSecommand BC3 = new BookCollapSecommand (BookService, 3L); BookCollapSecommand BC4 = new BookCollapSecommand (BookService, 4L); Future <Book> Q1 = BC1.Queue (); Future <Book> Q2 = BC2.Queue (); Future <Book> Q3 = BC3.Queue (); Livre livre1 = q1.get (); Livre livre2 = q2.get (); Livre de livres3 = q3.get (); Thread.Sleep (3000); Future <Book> Q4 = BC4.Queue (); Livre Book4 = Q4.get (); System.out.println ("book1 >>>" + book1); System.out.println ("Book2 >>>" + Book2); System.out.println ("Book3 >>>" + Book3); System.out.println ("Book4 >>>" + Book4); context.close ();}En ce qui concerne cette interface de test, j'ai dit les deux points suivants:
1. Tout d'abord, vous devez initialiser le HystrixRequestContext
2. Créez une instance de la classe BookCollapSecommand pour initier une demande, envoyez 3 demandes d'abord, puis dormez pendant 3 secondes, puis lancez une demande. De cette façon, les 3 premières demandes seront fusionnées en une seule demande. La quatrième demande ne sera pas fusionnée car l'intervalle entre eux est relativement long, mais créera un thread pour le traiter séparément.
Ok, jetons un coup d'œil aux résultats de l'exécution, comme suit:
La fusion de la demande est mise en œuvre par annotation
OK, la méthode de fusion de demande ci-dessus est un peu gênante à écrire, nous pouvons utiliser des annotations pour implémenter cette fonction plus élégamment. Tout d'abord, ajoutez deux méthodes dans BookService, comme suit:
@HystrixCollapser(batchMethod = "test11",collapserProperties = {@HystrixProperty(name ="timerDelayInMilliseconds",value = "100")})public Future<Book> test10(Long id) { return null;}@HystrixCommandpublic List<Book> test11(List<Long> ids) { System.out.println ("Test9 ----------" + IDS + "Thread.currentThread (). GetName ():" + Thread.currentThread (). GetName ()); Book [] books = restTemplate.getForObject ("http: // bonjour-service / getBook6? Ids = {1}", livre []. Class, stringUtils.join (ids, ",")); return arrays.aslist (livres);}Ajoutez l'annotation @hystrixCollapser pour implémenter la fusion de la demande sur la méthode Test10, utilisez l'attribut BatchMethod pour indiquer la méthode de traitement après la fusion de la demande et l'attribut CollapserProperties pour spécifier d'autres attributs.
OK, après l'avoir écrit dans BookService, appelez-le directement, comme suit:
@Requestmapping ("/ test8") @ réponsebodypublic void test8 () lève ExecutionException, interruptedException {HystrixRequestContext context = HystrixRequestContext.InitializEContext (); Future <Book> F1 = BookService.Test10 (1L); Futur <Book> f2 = bookservice.test10 (2l); Future <Book> F3 = BookService.Test10 (3L); Livre b1 = f1.get (); Livre b2 = f2.get (); Livre b3 = f3.get (); Thread.Sleep (3000); Future <Book> F4 = BookService.Test10 (4L); Livre b4 = f4.get (); System.out.println ("B1 >>>" + B1); System.out.println ("B2 >>>" + B2); System.out.println ("B3 >>>" + B3); System.out.println ("B4 >>>" + B4); context.close ();}Comme la précédente, les trois premières demandes seront fusionnées et la quatrième demande sera exécutée séparément. OK, et le résultat de l'exécution est le suivant:
Résumer
Avantages de la fusion des demandes, les amis ont vu que plusieurs demandes sont fusionnées dans une demande de traitement unique, ce qui peut économiser efficacement la bande passante du réseau et les ressources de pool de threads. Cependant, il existe des avantages et des inconvénients. Après avoir configuré la demande de demande, une demande a peut-être été terminée en 5 ms, mais vous devez maintenant attendre que 10 ms autres pour voir s'il y a d'autres demandes ensemble. De cette façon, la consommation de temps d'une demande sera passée de 5 ms à 15 ms. Cependant, si la commande que nous allons initier est une commande à un retard élevé, vous pouvez utiliser la demande de demande pour le moment, car la consommation de temps de la fenêtre temporelle est insignifiante pour le moment. De plus, une concurrence élevée est également un scénario très important pour les fusions de demande.
Ok, c'est tout pour notre demande de fusion. Si vous avez des questions, veuillez laisser un message et discuter. J'espère que cela sera utile à l'apprentissage de tous, et j'espère que tout le monde soutiendra davantage Wulin.com.