Organizaci贸n de la interacci贸n efectiva de microservicios.

Recientemente, las arquitecturas de microservicios han gozado de cierta popularidad. El rendimiento y la escalabilidad de las soluciones basadas en ellos pueden depender de c贸mo interact煤an los microservicios. Esta interacci贸n puede ser sincr贸nica o asincr贸nica. El material, cuya traducci贸n presentamos hoy a su atenci贸n, analiza m茅todos sincr贸nicos para la interacci贸n de microservicios. Es decir, nos centraremos en el estudio de dos tecnolog铆as: HTTP / 1.1 y gRPC. La primera tecnolog铆a est谩 representada por llamadas HTTP est谩ndar. El segundo se basa en el uso del marco RPC de alto rendimiento de Google. El autor del art铆culo sugiere mirar el c贸digo necesario para implementar la interacci贸n de microservicios utilizando HTTP / 1.1 y gRPC, tomar medidas de rendimiento y elegir una tecnolog铆a que permita organizar el intercambio de datos entre microservicios de la mejor manera.



Aplicaci贸n normal


Comencemos peque帽o y creemos un sistema de dos microservicios que puedan interactuar entre s铆. Tenga en cuenta que el modo de cl煤ster no se usa aqu铆. Aqu铆 hay un diagrama de nuestra aplicaci贸n.


Arquitectura de aplicaci贸n t铆pica

La aplicaci贸n consta de los siguientes componentes:

  • Herramienta de prueba del sistema: jMeter .
  • Servicio A: un microservicio que ejecuta solicitudes para el servicio B y devuelve las respuestas recibidas del mismo.
  • Servicio B (Servicio B): un microservicio que env铆a datos JSON est谩ticos en respuesta a solicitudes despu茅s de un retraso de 10 milisegundos, utilizado para todas sus API.
  • M谩quinas virtuales (VM 1 y VM 2): instancias Amazon EC2 t2.xlarge.

鈻岺TTP / 1.1


HTTP / 1.1 es una tecnolog铆a est谩ndar para organizar la interacci贸n de microservicios, que se utiliza cuando se utilizan bibliotecas HTTP como axios o superagent .

Aqu铆 est谩 el c贸digo de servicio B que implementa la API de nuestro sistema:

server.route({  method: 'GET',  path: '/',  handler: async (request, h) => {    const response = await new Promise((resolve) => {      setTimeout(() => {        resolve({          id: 1,          name: 'Abhinav Dhasmana',          enjoys_coding: true,        });      }, 10);    });    return h.response(response);  }, }); 

Aqu铆 est谩 el c贸digo para el servicio A que accede al servicio B usando HTTP / 1.1:

 server.route({ method: 'GET', path: '/', handler: async (request, h) => { try { const response = await Axios({ url: 'http://localhost:8001/', method: 'GET', }); return h.response(response.data); } catch (err) { throw Boom.clientTimeout(err); } }, }); 

Al ejecutar estos microservicios, podemos aprovechar jMeter para ejecutar pruebas de rendimiento. Descubriremos c贸mo se comporta el sistema cuando trabaje con 50 usuarios, cada uno de los cuales realiza 2000 solicitudes. Como se puede ver en la siguiente figura, la mediana de los resultados de la medici贸n es de 37 ms.


Resultados de la investigaci贸n de un sistema en modo normal usando HTTP / 1.1 usando jMeter

鈻峠RPC


gRPC utiliza la tecnolog铆a Protocol Buffers de forma predeterminada. Por lo tanto, usando gRPC, adem谩s del c贸digo de dos servicios, necesitaremos escribir el c贸digo de protoarchivo, que describe la interfaz entre los m贸dulos del sistema.

 syntax = "proto3"; service SampleDataService { rpc GetSampleData (Empty) returns (SampleData) {} } message SampleData { int32 id = 1; string name = 2; bool enjoys_coding = 3; } message Empty {} 

Ahora, dado que ahora planeamos usar gRPC, necesitamos reescribir el c贸digo de servicio B:

 const grpc = require('grpc'); const proto = grpc.load('serviceB.proto'); const server = new grpc.Server(); const GetSampleData = (call, callback) => { setTimeout(() => {   callback(null, {     id: 1,     name: 'Abhinav Dhasmana',     enjoys_coding: true,   }); }, 10); }; server.addService(proto.SampleDataService.service, { GetSampleData, }); const port = process.env.PORT; console.log('port', port); server.bind(`0.0.0.0:${port}`, grpc.ServerCredentials.createInsecure()); server.start(); console.log('grpc server is running'); 

Presta atenci贸n a algunas caracter铆sticas de este c贸digo:

  • El comando const server = new grpc.Server(); creamos un servidor grpc.
  • server.addService(proto... comando server.addService(proto... agregamos el servicio al servidor.
  • El comando server.bind(`0.0.0.0:${port}... se usa para vincular el puerto y las credenciales.

Ahora reescriba el servicio A usando gRPC:

 const protoPath = `${__dirname}/../serviceB/serviceB.proto`; const proto = grpc.load(protoPath); const client = new proto.SampleDataService('localhost:8001', grpc.credentials.createInsecure()); const getDataViagRPC = () => new Promise((resolve, reject) => { client.GetSampleData({}, (err, response) => {   if (!response.err) {     resolve(response);   } else {     reject(err);   } }); }); server.route({ method: 'GET', path: '/', handler: async (request, h) => {   const allResults = await getDataViagRPC();   return h.response(allResults); }, }); 

Entre las caracter铆sticas de este c贸digo est谩n las siguientes:

  • const client = new proto.SampleDataService... comando const client = new proto.SampleDataService... creamos un cliente grpc.
  • Se realiza una llamada remota utilizando el client.GetSampleData({}...

Ahora probemos lo que tenemos con jMeter.


Resultados de la investigaci贸n de un sistema en modo normal usando gRPC usando jMeter

Despu茅s de c谩lculos simples, puede descubrir que una soluci贸n que usa gRPC es un 27% m谩s r谩pida que una soluci贸n que usa HTTP / 1.1.

Aplicaci贸n de cl煤ster


Aqu铆 hay un diagrama de una aplicaci贸n similar a la que acabamos de investigar pero que funciona en modo de cl煤ster.


Arquitectura de aplicaci贸n en modo de cl煤ster

Si compara esta arquitectura con la considerada anteriormente, se pueden observar los siguientes cambios:

  • Hay un equilibrador de carga (Load Balancer), que usa NGINX .
  • El servicio B ahora est谩 presente en tres instancias que escuchan en diferentes puertos.

Una arquitectura similar es t铆pica para proyectos reales.

Explorando HTTP / 1.1 y gRPC en un nuevo entorno.

鈻岺TTP / 1.1


Cuando se utilizan microservicios que usan HTTP / 1.1 en un entorno en cl煤ster, su c贸digo no tendr谩 que modificarse. Solo necesita configurar nginx para organizar el equilibrio del tr谩fico del servicio B. En nuestro caso, para hacer esto, necesita traer el /etc/nginx/sites-available/default a este formulario:

 upstream httpservers {  server ip_address:8001;  server ip_address:8002;  server ip_address:8003; } server {  listen 80;  location / {     proxy_pass http://httpservers;  } } 

Ahora veamos lo que tenemos y veamos los resultados de probar el sistema usando jMeter.


Resultados de investigaci贸n para un sistema basado en cl煤ster que utiliza HTTP / 1.1 con jMeter

La mediana en este caso es de 41 ms.

鈻峠RPC


El soporte GRPC apareci贸 en nginx 1.13.10 . Por lo tanto, necesitamos la 煤ltima versi贸n de nginx, para cuya sudo apt-get install nginx comando sudo apt-get install nginx habitual no es adecuado.

Tambi茅n aqu铆 no utilizamos Node.js en modo de cl煤ster , ya que gRPC no es compatible con este modo.

Para instalar la 煤ltima versi贸n de nginx, use la siguiente secuencia de comandos:

 sudo apt-get install -y software-properties-common sudo add-apt-repository ppa:nginx/stable sudo apt-get update sudo apt-get install nginx 

Adem谩s, necesitaremos certificados SSL. Se puede crear un certificado autofirmado usando openSSL :

 openssl req -x509 -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' \ -keyout localhost-privatekey.pem -out localhost-certificate.pem 

Para usar gRPC, debe editar el archivo / etc/nginx/sites-available/default :

 upstream httpservers {  server ip_address:8001;  server ip_address:8002;  server ip_address:8003; } server {  listen 80;  location / {     proxy_pass http://httpservers;  } } 

Ahora todo est谩 listo para probar la soluci贸n gRPC de cl煤ster utilizando jMeter.


Resultados de un sistema en modo de cl煤ster usando gRPC usando jMeter

En este caso, la mediana es de 28 ms, que es un 31% m谩s r谩pida en comparaci贸n con el mismo indicador obtenido al examinar una soluci贸n HTTP / 1.1 agrupada.

Resumen


Los resultados del estudio muestran que una aplicaci贸n basada en microservicios que usa gRPC es aproximadamente un 30% m谩s productiva que una aplicaci贸n similar que usa HTTP / 1.1 para intercambiar datos entre microservicios. El c贸digo fuente de los proyectos discutidos en este art铆culo se puede encontrar aqu铆 .

Estimados lectores! Si est谩 desarrollando microservicios, hable acerca de c贸mo organizar el intercambio de datos entre ellos.

Source: https://habr.com/ru/post/es421579/


All Articles