Na arquitetura de microsserviços, dividimos um projeto em muitos módulos independentes, que trabalham juntos através de chamadas remotas. No entanto, no caso de alta concorrência, o aumento do número de comunicações levará a um aumento no tempo total de comunicação. Ao mesmo tempo, os recursos do pool de threads também são limitados. Um ambiente de alta concorrência fará com que um grande número de threads esteja em um estado de espera, o que levará a atrasos de resposta. Para resolver esses problemas, precisamos entender a fusão da solicitação da Hystrix.
A fusão da solicitação no Hystrix é usar um processador de mesclagem para mesclar solicitações consecutivas iniciadas pelo mesmo serviço em uma solicitação de processamento (a janela de tempo para essas solicitações contínuas é 10ms por padrão). Uma das classes principais envolvidas nesse processo é o HystrixCollapser, OK. Em seguida, vamos dar uma olhada em como implementar a fusão da solicitação Hystrix.
Interface do provedor de serviços
Preciso fornecer duas interfaces no provedor de serviços para os consumidores de serviço ligarem, como segue:
@RequestMapping ("/getBook6") Lista pública <Book> livro6 (string IDS) { System.out.println("ids>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 33, "hu shi", "nenhum")); Publishing House 2 "); Livro de Retorno;}A primeira interface é uma interface em lote e a segunda interface é uma interface que lida com uma única solicitação. Na interface do lote, o formato do parâmetro IDS enviado pelo consumidor de serviço é 1, 2, 3, 4 ... este formato. Em circunstâncias normais, precisamos consultar os dados correspondentes com base nos IDs e, em seguida, montá -los em um conjunto para retornar. Por uma questão de processamento fácil, retornarei o mesmo conjunto de dados, independentemente do tipo de solicitação; A interface para o processamento de uma única solicitação é relativamente simples, por isso não a repetirei.
Servindo consumidores
OK, depois que o provedor de serviços o lidou, vamos dar uma olhada em como os consumidores de serviço devem lidar com isso.
Serviço de Books
Primeiro, adicione dois métodos ao Service BookService para chamar a interface fornecida pelo provedor de serviços, como segue:
Public Book Test8 (Long Id) {Return Resttemplate.getForObject ("http: // hello-service/getBook6/{1}", book.class, id);} list <Book> test9 (list <long> ids) {System.out.println ("Test9 --------"+Ids+Ids) {System.out.println ("Test9 --------"++Ids+" Thread.currentThread (). GetName ()); Book [] books = RestTemplate.getForObject ("http: // hello -service/getbook6? Ids = {1}", livro []. Classe, stringutils.join (ids, ",")); Return Arrays.asList (Livros);}O teste8 é usado para chamar a interface que fornece um único ID, o teste9 é usado para chamar a interface que o processamento em lote. No Test9, imprimir o tópico em que o teste9 é executado para facilitar a observar os resultados da execução. Além disso, no Resttemplate, se o valor de retorno for uma coleção, precisamos recebê -lo primeiro com uma matriz e depois convertê -lo em uma coleção (talvez haja outros métodos, os amigos têm melhores sugestões a serem feitas).
BookbatchCommand
OK, depois que o método em BookService estiver pronto, podemos criar um BookBatchCommand, que é um comando em lote, como segue:
classe pública bookbatchCommand estende HystrixCommand <List <Book>> {List Private <Long> Ids; Service Service BookService; public bookbatchCommand (List <long> IDs, BookService BookService) {super (setter.withGroupKey (hystrixCommandgroupKey.factory.askey ("colapsingGroup")) .andCommandKey (hystrixCommandKey.Factory.askey ("collapsingKey"); this.ids = ids; this.BookService = BookService; } @Override Lista protegida <Book> run () lança a exceção {return bookservice.test9 (ids); }}Esta classe é realmente semelhante à classe que introduzimos no blog anterior. Ambos são herdados do HystrixCommand e são usados para lidar com solicitações mescladas e chamar o método Test9 no BookService no método de execução.
BookCollapsCommand
Em seguida, precisamos criar o bookcollapsCommand herdado a partir do hystrixcollapser para implementar a fusão da solicitação. do seguinte modo:
classe pública bookcollapsCommand estende HystrixCollapseer <List <Book>, livro, Long> {private BookService BookService; Private Long Id; public bookCollaPSECOMAND (BookService Service, Long Id) {super (setter.withCollapserKey (hystrixCollapserKey.factory.askey ("bookCollaPSecommand")). AndcollapsPropertiesDeFaults (HyStrixCollAsToSoSoSoSoSoSTERSTERSTERDERDERDELAY (HyStrixCoLAY (). this.BookService = BookService; this.id = id; } @Override public Long getRequestarGument () {return id; } @Override protegido HystrixCommand <List <Book>> CreateCommand (coleção <COLLAPSEDREQUEST <livro, Long>> colapsedRequests) {list <long> ids = new ArrayList <> (colapsedRequests.size ()); ids.addall (colapsedRequests.stream (). map (colapsedRequest :: getargument) .Collect (collectors.tolist ())); BookbatchCommand bookbatchCommand = new BookBatchCommand (IDS, BookService); retornar bookbatchCommand; } @Override Protected MapRESPONSETOREQUESTS (List <Book> BatchResponse, coleção <COLLAPSEDREQUEST <livro, Long>> colapsedRequests) {System.out.println ("mapReSponseTeQuests"); int conting = 0; para (colapsedRequest <Book, Long> colapsedRequest: colapsedRequests) {livro de livros = BatchResponse.get (count ++); colapsedRequest.setResponse (livro); }}}Em relação a esta aula, direi os seguintes pontos:
1. Primeiro de tudo, no método de construção, definimos a janela de tempo de solicitação para 100ms, ou seja, as solicitações com o intervalo de tempo de solicitação dentro de 100ms serão mescladas em uma solicitação.
2. O método CreateCommand é usado principalmente para mesclar solicitações, obter os IDs de cada solicitação aqui, colocar esses IDs únicos em uma coleção e, em seguida, criar um objeto BookBatchCommand e usar esse objeto para iniciar uma solicitação de lotes.
3. O método MapRESPONETOREQUESTS é usado principalmente para definir o resultado da solicitação para cada solicitação. O primeiro parâmetro deste método representa o resultado da solicitação em lote, e o segundo parâmetro colapsedRequests representa cada solicitação mesclada. Em seguida, definimos o resultado da solicitação para requestrões em colapso atravessando BatchResponse.
OK, depois que todas essas operações forem concluídas, podemos ir e testá -las.
teste
Criamos uma interface de acesso no lado do consumidor de serviço para testar a solicitação de mesclagem. A interface de teste é a seguinte:
@RequestMapping ("/test7")@ResponseBodyPublic void test7 () lança ExecutionException, interruptEdException {hystrixRrixRequestContext context = hystrixRrixRequestContext.initializeContext (); BookcollapsCommand bc1 = novo bookcollapsCommand (BookService, 1L); BookcollapsCommand bc2 = novo bookcollapsCommand (BookService, 2L); BookcollapsCommand bc3 = novo bookcollapsCommand (BookService, 3L); BookcollapsCommand bc4 = novo bookcollapsCommand (BookService, 4L); Futuro <Book> q1 = bc1.queue (); Futuro <Book> q2 = bc2.queue (); Futuro <Book> q3 = bc3.queue (); Livro do livro1 = Q1.get (); Livro de livros2 = q2.get (); Livro do livro3 = Q3.get (); Thread.sleep (3000); Futuro <Book> q4 = bc4.queue (); Livro de livros4 = Q4.get (); System.out.println ("livro1 >>>"+livro1); System.out.println ("livro2 >>>"+livro2); System.out.println ("livro3 >>>"+livro3); System.out.println ("livro4 >>>"+livro4); context.Close ();}Em relação a esta interface de teste, eu disse os dois pontos a seguir:
1. Primeiro, você precisa inicializar o HystrixRequestContext
2. Crie uma instância da classe BookCollaPSecommand para iniciar uma solicitação, envie 3 solicitações primeiro, depois durma por 3 segundos e depois inicie uma solicitação. Dessa forma, as três primeiras solicitações serão mescladas em uma solicitação. A quarta solicitação não será mesclada porque o intervalo entre eles é relativamente longo, mas criará um thread para processá -lo separadamente.
Ok, vamos dar uma olhada nos resultados da execução, como segue:
A fusão de solicitação é implementada por anotações
OK, o método de fusão de solicitação acima é um pouco problemático para escrever, podemos usar anotações para implementar essa função com mais elegância. Primeiro, adicione dois métodos no BookService, como segue:
@Hystrixcollapser (Batchmethod = "test11", colapserProperties = {@hystrixProperty (name = "timelerDelayinMillisEconds", value = "100")}) public Future <Book> test10 (Long id) {Return null; System.out.println ("test9 ----------"+ids+"thread.currentThread (). GetName ():"+thread.currentThread (). GetName ()); Book [] books = RestTemplate.getForObject ("http: // hello -service/getbook6? Ids = {1}", livro []. Classe, stringutils.join (ids, ",")); Return Arrays.asList (Livros);}Adicione a anotação @hystrixcollaper para implementar a mesclagem de solicitação no método Test10, use o atributo BatchMethod para indicar o método de processamento após a mesclagem de solicitação e o atributo colapserProperties para especificar outros atributos.
OK, depois de escrevê -lo no BookService, basta chamá -lo diretamente, como segue:
@RequestMapping ("/test8")@ResponseBodyPublic void test8 () lança ExecutionException, interruptedException {hystrixRrixRequestContext context = hystrixRrixRequestContext.initializeContext (); Future <Book> F1 = BookService.test10 (1L); Future <Book> f2 = BookService.test10 (2L); Future <Book> f3 = BookService.test10 (3L); Livro b1 = f1.get (); Livro b2 = f2.get (); Livro B3 = F3.get (); Thread.sleep (3000); Future <Book> f4 = BookService.test10 (4L); Livro 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 ();}Como o anterior, as três primeiras solicitações serão mescladas e a quarta solicitação será executada separadamente. Ok, e o resultado da execução é o seguinte:
Resumir
Vantagens da fusão de solicitação, os amigos viram que várias solicitações são fundidas em uma solicitação de processamento único, que pode economizar efetivamente a largura de banda de rede e os recursos do pool de threads. No entanto, existem vantagens e desvantagens. Depois de configurar a fusão da solicitação, uma solicitação pode ter sido concluída em 5ms, mas agora você deve esperar mais 10 ms para ver se existem outras solicitações juntas. Dessa forma, o consumo de tempo de uma solicitação será aumentado de 5ms para 15ms. No entanto, se o comando que iniciarmos for um comando de alto atraso, você poderá usar a fusão da solicitação no momento, porque o consumo de tempo da janela de tempo é insignificante no momento. Além disso, a alta concorrência também é um cenário muito importante para fusões de solicitação.
OK, isso é tudo para que nosso pedido se fundamenta. Se você tiver alguma dúvida, deixe uma mensagem e discuta. Espero que seja útil para o aprendizado de todos, e espero que todos apoiem mais o wulin.com.