Estamos escribiendo el primer microservicio en Node.js con comunicación a través de RabbitMQ

Con el tiempo, cada proyecto crece e implementar nuevas funciones en un monolito existente se vuelve más difícil, más largo y más costoso para las empresas.


Una de las soluciones a este problema es el uso de la arquitectura de microservicios. Para los principiantes o para aquellos que son nuevos en esta arquitectura por primera vez, puede ser difícil saber por dónde empezar, qué hay que hacer y qué no vale la pena hacer.


Este artículo escribirá el microservicio más simple en Nodejs & RabbitMQ, y también muestra el proceso de migración de un monolito a microservicios.


¿Qué hay en la arquitectura de microservicios?


  1. Puerta de enlace El servidor principal que recibe las solicitudes y las redirige al microservicio deseado. Más a menudo que no, no hay lógica de negocios en la puerta de enlace.
  2. Microservicio El propio microservicio, que procesa las solicitudes de los usuarios con una lógica empresarial claramente definida.
  3. Transporte Esta es la parte a través de la cual Gateway y Microservice se comunicarán. El transporte puede ser HTTP, gRPC, RabbitMQ, etc.

¿Por qué RabbitMQ?


Por supuesto, no puede usar RabbitMQ, hay otras opciones para la comunicación entre microservicios. El más simple es HTTP, hay gRPC de Google.


Uso RabbitMQ, porque me parece bastante simple comenzar a escribir microservicios, confiable y conveniente, ya que puede estar seguro de que cuando se envía un mensaje a la cola, el mensaje llegará al microservicio (incluso si está apagado en ese momento y luego encendido) ) Gracias a estas ventajas, puede escribir microservicios confiables y utilizar una implementación perfecta.


Inicio


Primero, implementamos una puerta de enlace simple que recibirá solicitudes HTTP mientras escucha un puerto específico.


Implementamos RabbitMQ (a través de él se comunicarán nuestros microservicios y puerta de enlace):


$ docker run -d -p 5672:5672 rabbitmq 

Inicializamos el proyecto e instalamos el paquete micromq NPM:


 $ npm init -y $ npm i micromq -S 

Escribir un portal


 //   Gateway     micromq const Gateway = require('micromq/gateway'); //    Gateway const app = new Gateway({ //  ,      microservices: ['users'], //  rabbitmq rabbit: { //     rabbitmq (default: amqp://guest:guest@localhost:5672) url: process.env.RABBIT_URL, }, }); //    /friends & /status   GET app.get(['/friends', '/status'], async (req, res) => { //     users await res.delegate('users'); }); //    app.listen(process.env.PORT); 

Cómo funcionará:


  1. El servidor se inicia, comienza a escuchar el puerto y recibe solicitudes
  2. El usuario envía una solicitud a https://mysite.com/friends
  3. Gateway, de acuerdo con la lógica que describimos, delega la solicitud:
    3.1 Se está enviando un mensaje (parámetros de solicitud, encabezados, información de conexión, etc.) a la cola RabbitMQ
    3.2. El microservicio escucha esta cola, procesa una nueva solicitud
    3.3. Microservicio envía una respuesta a la cola
    3.4. Gateway escucha una cola de respuesta, recibe una respuesta de un microservicio
    3.5. Gateway envía una respuesta al cliente
  4. El usuario recibe una respuesta.

Escribimos un microservicio


 //   MicroService     micromq const MicroMQ = require('micromq'); //    MicroService const app = new MicroMQ({ //   (    ,    Gateway) name: 'users', //  rabbitmq rabbit: { //     rabbitmq (default: amqp://guest:guest@localhost:5672) url: process.env.RABBIT_URL, }, }); //   /friends   GET app.get('/friends', (req, res) => { //  json  res.json([ { id: 1, name: 'Mikhail Semin', }, { id: 2, name: 'Ivan Ivanov', }, ]); }); //   /status   GET app.get('/status', (req, res) => { //  json  res.json({ text: 'Thinking...', }); }); //     app.start(); 

Cómo funcionará:


  1. Se inicia el microservicio, comienza a escuchar la cola de solicitud en la que Gateway escribirá.
  2. El microservicio recibe la solicitud, la procesa y ejecuta todos los middlewares disponibles.
  3. Microservicio envía una respuesta a Gateway
    3.1. Se está enviando un mensaje (encabezados, cuerpo de respuesta de código HTTP) a la cola RabbitMQ
    3.2. Gateway escucha esta cola, recibe un mensaje, encuentra un cliente al que necesita enviar una respuesta
    3.3 Gateway envía una respuesta al cliente

Migración de monolitos a arquitectura de microservicios


Supongamos que ya tenemos una aplicación express y queremos comenzar a portarla a microservicios.


Se ve así:


 const express = require('express'); const app = express(); app.get('/balance', (req, res) => { res.json({ amount: 500, }); }); app.get('/friends', (req, res) => { res.json([ { id: 1, name: 'Mikhail Semin', }, { id: 2, name: 'Ivan Ivanov', }, ]); }); app.get('/status', (req, res) => { res.json({ text: 'Thinking...', }); }); app.listen(process.env.PORT); 

Queremos obtener 2 puntos finales: / amigos y / estado. ¿Qué necesitamos hacer para esto?


  1. Lleve la lógica de negocios a un microservicio
  2. Implemente la delegación de solicitudes para estos dos puntos finales al microservicio
  3. Obtenga respuesta del microservicio
  4. Enviar respuesta al cliente

En el ejemplo anterior, cuando creamos el microservicio de los usuarios, implementamos dos métodos / amigos y / estado, que hacen lo mismo que nuestro monolito.


Para poder enviar solicitudes de proxy al microservicio desde la puerta de enlace, utilizaremos el mismo paquete conectando el middleware a nuestra aplicación express:


 const express = require('express'); //   Gateway     micromq const Gateway = require('micromq/gateway'); const app = express(); //    Gateway const gateway = new Gateway({ //   (    ,    Gateway) microservices: ['users'], //  rabbitmq rabbit: { //     rabbitmq (default: amqp://guest:guest@localhost:5672) url: process.env.RABBIT_URL, }, }); //  middleware  ,      app.use(gateway.middleware()); //    ,          app.get('/balance', (req, res) => { res.json({ amount: 500, }); }); //    /friends & /status   GET app.get(['/friends', '/status'], async (req, res) => { //     users //  res.delegate   middleware,     await res.delegate('users'); }); //   app.listen(process.env.PORT); 

Esto funciona de la misma manera que en el ejemplo anterior, donde escribimos una puerta de enlace limpia. En este ejemplo, la única diferencia es que no es Gateway lo que acepta solicitudes, sino un monolito escrito en forma expresa.


Que sigue


  1. RPC (llamada de acción remota) de un microservicio a un monolito / puerta de enlace (por ejemplo, para autorización)
  2. Comuníquese entre microservicios a través de las colas RabbitMQ para obtener más información, porque cada microservicio tiene su propia base de datos

Ya lo dije en el artículo "Aprendiendo a comunicarse entre microservicios en Node.js a través de RabbitMQ" .


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


All Articles