En la arquitectura de microservicio, dividimos un proyecto en muchos módulos independientes, que funcionan juntos a través de llamadas remotas. Sin embargo, en el caso de alta concurrencia, el aumento en el número de comunicaciones conducirá a un aumento en el tiempo de comunicación total. Al mismo tiempo, los recursos del grupo de subprocesos también son limitados. Un entorno de alta concurrencia hará que una gran cantidad de hilos estén en un estado de espera, lo que conducirá a retrasos de respuesta. Para resolver estos problemas, necesitamos comprender la fusión de solicitudes de Hystrix.
La fusión de la solicitud en Hystrix es utilizar un procesador de fusión para fusionar solicitudes consecutivas iniciadas por el mismo servicio en una solicitud de procesamiento (la ventana de tiempo para estas solicitudes continuas es de 10 ms de forma predeterminada). Una de las clases centrales involucradas en este proceso es HystrixCollapser, OK. A continuación, echemos un vistazo a cómo implementar la fusión de solicitudes de Hystrix.
Interfaz del proveedor de servicios
Necesito proporcionar dos interfaces en el proveedor de servicios para que los consumidores de servicios llamen, de la siguiente manera:
@RequestMapping ("/getbook6") Lista pública <Book> Book6 (IDS de cadena) { System.out.println ("IDS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> en >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 33, "Hu Shi", "Ninguno")); Literatura editorial 2 "); Libro de regreso;}La primera interfaz es una interfaz por lotes y la segunda interfaz es una interfaz que maneja una sola solicitud. En la interfaz por lotes, el formato de parámetro IDS enviado por el consumidor del servicio es 1, 2, 3, 4 ... este formato. En circunstancias normales, necesitamos consultar los datos correspondientes en función de las ID y luego ensamblarlos en un conjunto para devolver. En aras del fácil procesamiento, devolveré el mismo conjunto de datos sin importar qué tipo de solicitud; La interfaz para procesar una sola solicitud es relativamente simple, por lo que no la repetiré.
Sirviendo a los consumidores
Ok, después de que el proveedor de servicios lo haya manejado, echemos un vistazo a cómo los consumidores de servicios deben manejarlo.
Servicio de libros
Primero, agregue dos métodos al servicio de libros para llamar a la interfaz proporcionada por el proveedor de servicios, de la siguiente manera:
Public Book Test8 (Long Id) {return RestTemplate.getForObject ("http: // hello-service/getbook6/{1}", book.class, id);} public List <Book> test9 (list <Long> ids) {system.println ("test9 -------------"+ids+"Thread.currentThread ().). Thread.CurrentThread (). GetName ()); Book [] books = ResttEmplate.getForObject ("http: // hello-service/getBook6? Ids = {1}", libro []. Class, stringUtils.Join (ids, ","); matrices de retorno.aslist (libros);}Test8 se utiliza para llamar a la interfaz que proporciona una sola ID, Test9 se usa para llamar a la interfaz que el procesamiento por lotes. En Test9, imprimo el hilo donde se ejecuta Test9 para facilitarnos observar los resultados de la ejecución. Además, en RestTemplate, si el valor de retorno es una colección, tenemos que recibirla primero con una matriz, y luego convertirla en una colección (tal vez hay otros métodos, los amigos tienen mejores sugerencias que hacer).
Bookbatchcommand
Ok, después de que el método en BookService esté listo, podemos crear un BookBatchCommand, que es un comando por lotes, como sigue:
Public Class BookBatchCommand extiende HystrixCommand <List <Book> {Lista privada <Anconte> IDS; Bookservice de libros privados; Public BookBatchCommand (List <Long> IDS, BookService Bookservice) {super (setter.withgroupkey (hytrixcommandgroupkey.factory.askey ("colapsinggroup"))) .yCommandKey (hystrixCommandkey.factory.askey ("colapsingkey"))); this.ids = ids; this.bookService = bookservice; } @Override Lista protegida <Book> run () lanza excepción {return bookservice.test9 (IDS); }}Esta clase es realmente similar a la clase que presentamos en el blog anterior. Ambos se heredan de HystrixCommand y se utilizan para manejar las solicitudes fusionadas y llamar al método Test9 en BookService en el método Ejecutar.
Bookcollapsecommand
A continuación, necesitamos crear BookCollaPsecommand heredado de HystrixCollapser para implementar la fusión de solicitudes. como sigue:
Public Class BookCollapsecommand extiende HystrixCollapseer <List <Book>, Libro, Long> {servicio privado de libros bookservice; ID de larga prudente; Public BookCollaPsecommand (BookService BookService, Long ID) {super (setter.withCollaPserkey (hytrixCollapserkey.factory.askey ("bookcollapsecommand")). andcollaPserPropertiesdefaults (hystrixColserPreperties.setter (). this.bookService = bookservice; this.id = id; } @Override public Long getRequestarGument () {return id; } @Override HystrixCommand <List <Book>> CreateCommand (Collection <collapsedRequest <book, long >> collapsedRequests) {list <Long> ids = new ArrayList <> (collapsedRequests.size ()); IDS.Addall (collapsedRequests.stream (). BookBatchCommand BookBatchCommand = nuevo BookBatchCommand (IDS, BookService); regresar BookBatchCommand; } @Override void mapResponseSetorequests (List <Book> BatchResponse, Collection <collapsedRequest <Book, long >> collapsedRequests) {system.out.println ("mapResponseSetoreQuests"); int count = 0; para (collapsedRequest <book, long> collapsedRequest: collapsedrequests) {book book = batchResponse.get (count ++); collapsedRequest.setResponse (libro); }}}Con respecto a esta clase, diré los siguientes puntos:
1. En primer lugar, en el método de construcción, establecemos la ventana de tiempo de solicitud en 100 ms, es decir, las solicitudes con el intervalo de tiempo de solicitud dentro de los 100 ms se fusionarán en una sola solicitud.
2. El método CreateCommand se usa principalmente para fusionar las solicitudes, obtener las ID de cada sola solicitud aquí, colocar estas ID de una sola colección y luego crear un objeto BookBatchCommand y usar este objeto para iniciar una solicitud de lotes.
3. El método MapResponsetorequests se usa principalmente para establecer el resultado de la solicitud para cada solicitud. El primer parámetro de este método representa el resultado de la solicitud por lotes, y el segundo parámetro colapsedRequests representa cada solicitud fusionada. Luego establecemos el resultado de la solicitud de requisitos de colapso al atravesar BatchResponse.
Ok, después de completar todas estas operaciones, podemos venir y probarlo.
prueba
Creamos una interfaz de acceso en el lado del consumidor del servicio para probar la solicitud de fusión. La interfaz de prueba es la siguiente:
@RequestMapping ("/test7")@ResponseBodyPublic Void test7 () lanza ExecutionException, InterruptedException {HystrixRequestContext context = HystrixRequestContext.InitializeContext (); BookCollaPsecommand BC1 = nuevo BookCollaPsecommand (Bookservice, 1L); BookCollaPsecommand BC2 = nuevo BookCollaPsecommand (Bookservice, 2L); BookCollaPsecommand BC3 = nuevo BookCollaPsecommand (Bookservice, 3L); BookCollaPsecommand BC4 = nuevo BookCollaPsecommand (Bookservice, 4L); Futuro <Book> Q1 = BC1.Queue (); Futuro <Book> Q2 = bc2.queue (); Futuro <Book> Q3 = bc3.queue (); Libro book1 = q1.get (); Libro book2 = q2.get (); Libro Book3 = Q3.get (); Thread.sleep (3000); Futuro <Book> Q4 = bc4.queue (); Libro 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 ();}Con respecto a esta interfaz de prueba, dije los siguientes dos puntos:
1. Primero, debe inicializar el HytrixRequestContext
2. Cree una instancia de BookCollaPsecommand Class para iniciar una solicitud, envíe 3 solicitudes primero, luego duerma durante 3 segundos e inicie una solicitud. De esta manera, las primeras 3 solicitudes se fusionarán en una sola solicitud. La cuarta solicitud no se fusionará porque el intervalo entre ellos es relativamente largo, pero creará un hilo para procesarlo por separado.
Ok, echemos un vistazo a los resultados de la ejecución, de la siguiente manera:
La solicitud de fusión se implementa a través de la anotación
Ok, el método de fusión de solicitud anterior es un poco problemático de escribir, podemos usar anotaciones para implementar esta función de manera más elegante. Primero, agregue dos métodos en BookService, como sigue:
@HyStriXCollApSer (batchmethod = "test11", collapserProperties = {@HyStrixproperty (name = "timerDelayInMilliseConds", value = "100")}) Public Future <BODSE> 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}", libro []. Class, stringUtils.Join (ids, ","); matrices de retorno.aslist (libros);}Agregue la anotación de @hystrixcollapser para implementar la fusión de solicitudes en el método test10, use el atributo BatchMethod para indicar el método de procesamiento después de la solicitud de fusión, y el atributo de colapserProperties para especificar otros atributos.
Ok, después de escribirlo en BookService, solo llámalo directamente, de la siguiente manera:
@RequestMapping ("/test8")@ResponseBodyPublic Void test8 () lanza ExecutionException, InterruptedException {HystrixRequestContext context = HystrixRequestContext.InitializeContext (); Futuro <Book> F1 = Bookservice.test10 (1L); Futuro <Book> f2 = bookservice.test10 (2l); Futuro <Book> f3 = bookservice.test10 (3l); Libro b1 = f1.get (); Libro b2 = f2.get (); Libro b3 = f3.get (); Thread.sleep (3000); Futuro <Book> f4 = bookservice.test10 (4l); Libro 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 ();}Al igual que el anterior, las primeras tres solicitudes se fusionarán y la cuarta solicitud se ejecutará por separado. OK, y el resultado de la ejecución es el siguiente:
Resumir
Ventajas de la fusión de solicitudes, los amigos han visto que múltiples solicitudes se fusionan en una solicitud de procesamiento único, lo que puede ahorrar efectivamente el ancho de banda de la red y los recursos de la piscina de subprocesos. Sin embargo, hay ventajas y desventajas. Después de configurar la fusión de la solicitud, podría haberse completado una solicitud en 5 ms, pero ahora debe esperar a otros 10 ms para ver si hay alguna otra solicitud juntos. De esta manera, el consumo de tiempo de una solicitud se incrementará de 5 ms a 15 ms. Sin embargo, si el comando que vamos a iniciar es un comando de alta retardo, entonces puede usar la solicitud de fusión en este momento, porque el consumo de tiempo de la ventana de tiempo es insignificante en este momento. Además, la alta concurrencia también es un escenario muy importante para las fusiones de solicitud.
Ok, eso es todo para nuestra solicitud de fusionar. Si tiene alguna pregunta, deje un mensaje y discuta. Espero que sea útil para el aprendizaje de todos, y espero que todos apoyen más a Wulin.com.