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铆picaLa 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 jMeterDespu茅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煤sterSi 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 jMeterLa 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 jMeterEn 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.
