Estamos escrevendo o primeiro microsserviço no Node.js com comunicação através do RabbitMQ

Com o tempo, cada projeto cresce e a implementação de novas funcionalidades em um monólito existente se torna mais difícil, mais longa e mais cara para os negócios.


Uma das soluções para esse problema é o uso da arquitetura de microsserviço. Para iniciantes ou iniciantes nessa arquitetura pela primeira vez, pode ser difícil descobrir por onde começar, o que precisa ser feito e o que não vale a pena.


Este artigo escreverá o microsserviço mais simples no Nodejs e RabbitMQ e também mostra o processo de migração de um monólito para microsserviços.


O que há na arquitetura de microsserviço?


  1. Gateway O servidor principal que recebe solicitações e as redireciona para o microsserviço desejado. Na maioria das vezes, não há lógica de negócios no gateway.
  2. Microsserviço. O próprio microsserviço, que processa solicitações do usuário com lógica de negócios claramente definida.
  3. Transporte Essa é a parte pela qual o Gateway & Microservice se comunicará. O transporte pode ser HTTP, gRPC, RabbitMQ, etc.

Porquê RabbitMQ?


Obviamente, você não pode usar o RabbitMQ, existem outras opções de comunicação entre microsserviços. O mais simples é o HTTP, existe o gRPC do Google.


Eu uso o RabbitMQ, porque acho bastante simples começar a escrever microsserviços, confiáveis ​​e convenientes, pois você pode ter certeza de que, quando uma mensagem é enviada para a fila, a mensagem chegará ao microsserviço (mesmo que esteja desativado no momento e depois ligado) ) Graças a essas vantagens, você pode escrever microsserviços confiáveis ​​e usar uma implantação contínua.


Iniciar


Primeiro, implementamos um gateway simples que receberá solicitações HTTP enquanto ouve uma porta específica.


Implementamos o RabbitMQ (através dele nossos microsserviços e gateway se comunicarão):


$ docker run -d -p 5672:5672 rabbitmq 

Inicializamos o projeto e instalamos o pacote micromq NPM:


 $ npm init -y $ npm i micromq -S 

Escrevendo um gateway


 //   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); 

Como vai funcionar:


  1. O servidor inicia, começa a ouvir a porta e a receber solicitações
  2. O usuário envia uma solicitação para https://mysite.com/friends
  3. O gateway, de acordo com a lógica que descrevemos, delega a solicitação:
    3.1 Uma mensagem está sendo enviada (parâmetros de solicitação, cabeçalhos, informações de conexão etc.) para a fila RabbitMQ
    3.2 O microsserviço ouve essa fila, processa uma nova solicitação
    3.3 Microservice envia uma resposta para a fila
    3.4 O gateway escuta uma fila de resposta, recebe uma resposta de um microsserviço
    3.5 O gateway envia uma resposta ao cliente
  4. O usuário recebe uma resposta.

Escrevemos um microsserviço


 //   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(); 

Como vai funcionar:


  1. O microsserviço é iniciado, começa a ouvir a fila de solicitações na qual o Gateway gravará.
  2. O microsserviço recebe a solicitação, processa-a, executando todos os middlewares disponíveis
  3. Microservice envia uma resposta ao Gateway
    3.1 A mensagem está sendo enviada (cabeçalhos, corpo de resposta do código HTTP) para a fila RabbitMQ
    3.2 O gateway escuta essa fila, recebe uma mensagem, encontra um cliente para o qual precisa enviar uma resposta
    3.3 Gateway envia uma resposta para o cliente

Migração de monólito para arquitetura de microsserviço


Suponha que já tenhamos um aplicativo expresso e desejemos começar a portá-lo para microsserviços.


É assim:


 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 obter 2 pontos finais: / friends e / status. O que precisamos fazer para isso?


  1. Coloque a lógica de negócios em um microsserviço
  2. Implementar a delegação de solicitações para esses dois pontos de extremidade no microsserviço
  3. Obtenha resposta do microsserviço
  4. Enviar resposta ao cliente

No exemplo acima, quando criamos o microsserviço de usuários, implementamos dois métodos / friends e / status, que fazem a mesma coisa que o nosso monólito.


Para solicitar solicitações de proxy ao microsserviço do gateway, usaremos o mesmo pacote conectando o middleware ao nosso aplicativo expresso:


 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); 

Isso funciona da mesma maneira que no exemplo acima, onde escrevemos um Gateway limpo. Neste exemplo, a única diferença é que não é o Gateway que aceita solicitações, mas um monólito escrito em expresso.


O que vem a seguir


  1. RPC (chamada de ação remota) de um microsserviço para um monólito / gateway (por exemplo, para autorização)
  2. Comunique-se entre microsserviços através de filas RabbitMQ para obter mais informações, porque cada microsserviço possui seu próprio banco de dados

Eu já disse isso no artigo "Aprendendo a se comunicar entre microsserviços no Node.js através do RabbitMQ" .


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


All Articles