Nous écrivons le premier microservice sur Node.js avec communication via RabbitMQ

Au fil du temps, chaque projet se développe et la mise en œuvre de nouvelles fonctionnalités dans un monolithe existant devient plus difficile, plus longue et plus coûteuse pour les entreprises.


L'une des solutions à ce problème est l'utilisation d'une architecture de microservices. Pour les débutants ou pour ceux qui découvrent cette architecture pour la première fois, il peut être difficile de savoir par où commencer, ce qui doit être fait et ce qui ne vaut pas la peine.


Cet article va écrire le microservice le plus simple sur Nodejs & RabbitMQ, et montre également le processus de migration d'un monolithe vers les microservices.


Qu'est-ce que dans l'architecture de microservices?


  1. Passerelle Le serveur principal qui reçoit les demandes et les redirige vers le microservice souhaité. Plus souvent qu'autrement, il n'y a pas de logique métier dans la passerelle.
  2. Microservice. Le microservice lui-même, qui traite les demandes des utilisateurs avec une logique métier clairement définie.
  3. Le transport C'est la partie par laquelle Gateway & Microservice communiquera. Le transport peut être HTTP, gRPC, RabbitMQ, etc.

Pourquoi RabbitMQ?


Bien sûr, vous ne pouvez pas utiliser RabbitMQ, il existe d'autres options pour la communication entre les microservices. Le plus simple est HTTP, il y a le gRPC de Google.


J'utilise RabbitMQ, car je le trouve assez simple pour commencer à écrire des microservices, fiable et pratique en ce sens que vous pouvez être sûr que lorsqu'un message est envoyé dans la file d'attente, le message atteindra le microservice (même s'il est désactivé pour le moment puis allumé) ) Grâce à ces avantages, vous pouvez écrire des microservices fiables et utiliser un déploiement transparent.


Commencer


Tout d'abord, nous implémentons une passerelle simple qui recevra les requêtes HTTP tout en écoutant un port spécifique.


Nous déployons RabbitMQ (à travers lui nos microservices et notre passerelle communiqueront):


$ docker run -d -p 5672:5672 rabbitmq 

Nous initialisons le projet et installons le package micromq NPM:


 $ npm init -y $ npm i micromq -S 

Écrire une passerelle


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

Comment cela fonctionnera:


  1. Le serveur démarre, il écoute le port et reçoit les requêtes
  2. L'utilisateur envoie une demande à https://mysite.com/friends
  3. Gateway, selon la logique que nous avons décrite, délègue la demande:
    3.1 Un message est envoyé (paramètres de requête, en-têtes, informations de connexion, etc.) à la file d'attente RabbitMQ
    3.2. Le microservice écoute cette file d'attente, traite une nouvelle demande
    3.3. Le microservice envoie une réponse à la file d'attente
    3.4. La passerelle écoute une file d'attente de réponses, reçoit une réponse d'un microservice
    3.5. La passerelle envoie une réponse au client
  4. L'utilisateur reçoit une réponse.

Nous écrivons un microservice


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

Comment cela fonctionnera:


  1. Le microservice démarre, commence à écouter la file d'attente de demandes dans laquelle Gateway va écrire.
  2. Le microservice reçoit la demande, la traite et traverse tous les middlewares disponibles
  3. Le microservice envoie une réponse à Gateway
    3.1. Le message est envoyé (en-têtes, corps de réponse du code HTTP) à la file d'attente RabbitMQ
    3.2. La passerelle écoute cette file d'attente, reçoit un message, trouve un client à qui elle doit envoyer une réponse
    3.3 La passerelle envoie une réponse au client

Migration de monolithes vers une architecture de microservices


Supposons que nous ayons déjà une application express et que nous voulons commencer à la porter sur des microservices.


Cela ressemble à ceci:


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

Nous voulons en retirer 2 points de terminaison: / friends et / status. Que devons-nous faire pour cela?


  1. Tirez la logique métier dans un microservice
  2. Implémenter la délégation des demandes de ces deux points de terminaison au microservice
  3. Obtenez une réponse du microservice
  4. Envoyer une réponse au client

Dans l'exemple ci-dessus, lorsque nous avons créé le microservice des utilisateurs, nous avons implémenté deux méthodes / friends et / status, qui font la même chose que notre monolith.


Afin de proxy les demandes au microservice de la passerelle, nous utiliserons le même package en connectant le middleware à notre application 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); 

Cela fonctionne de la même manière que dans l'exemple ci-dessus, où nous avons écrit une passerelle propre. Dans cet exemple, la seule différence est que ce n'est pas Gateway qui accepte les requêtes, mais un monolithe écrit en express.


Et ensuite


  1. RPC (appel à distance) d'un microservice à un monolith / passerelle (par exemple, pour l'autorisation)
  2. Communiquez entre les microservices via les files d'attente RabbitMQ pour plus d'informations, car chaque microservice possède sa propre base de données

Je l'ai déjà dit dans l'article «Apprendre à communiquer entre les microservices sur Node.js via RabbitMQ» .


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


All Articles