Wir schreiben den ersten Microservice auf Node.js mit Kommunikation über RabbitMQ

Mit der Zeit wächst jedes Projekt und die Implementierung neuer Funktionen in einen vorhandenen Monolithen wird für Unternehmen schwieriger, länger und teurer.


Eine der Lösungen für dieses Problem ist die Verwendung einer Microservice-Architektur. Für Anfänger oder diejenigen, die diese Architektur zum ersten Mal kennen, kann es schwierig sein, herauszufinden, wo sie anfangen sollen, was getan werden muss und was es nicht wert ist, getan zu werden.


Dieser Artikel beschreibt den einfachsten Microservice für Nodejs & RabbitMQ und zeigt auch den Prozess der Migration eines Monolithen zu Microservices.


Was ist in der Microservice-Architektur?


  1. Gateway Der Hauptserver, der Anforderungen empfängt und an den gewünschten Mikrodienst umleitet. Meistens gibt es keine Geschäftslogik im Gateway.
  2. Microservice. Der Microservice selbst, der Benutzeranforderungen mit klar definierter Geschäftslogik verarbeitet.
  3. Transport Dies ist der Teil, über den Gateway & Microservice kommunizieren wird. Der Transport kann HTTP, gRPC, RabbitMQ usw. sein.

Warum RabbitMQ?


Natürlich können Sie RabbitMQ nicht verwenden, es gibt andere Optionen für die Kommunikation zwischen Microservices. Am einfachsten ist HTTP, es gibt gRPC von Google.


Ich verwende RabbitMQ, weil ich es einfach genug finde, mit dem Schreiben von Microservices zu beginnen. Dies ist zuverlässig und praktisch, da Sie sicher sein können, dass die Nachricht durch Senden einer Nachricht an die Warteschlange den Microservice erreicht (auch wenn sie gerade ausgeschaltet und dann eingeschaltet ist ) Dank dieser Vorteile können Sie zuverlässige Microservices schreiben und eine nahtlose Bereitstellung verwenden.


Starten Sie


Zunächst implementieren wir ein einfaches Gateway, das HTTP-Anforderungen empfängt, während ein bestimmter Port abgehört wird.


Wir setzen RabbitMQ ein (dadurch kommunizieren unsere Microservices und unser Gateway):


$ docker run -d -p 5672:5672 rabbitmq 

Wir initialisieren das Projekt und installieren das micromq NPM-Paket:


 $ npm init -y $ npm i micromq -S 

Ein Gateway schreiben


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

Wie es funktionieren wird:


  1. Der Server startet, hört den Port ab und empfängt Anforderungen
  2. Der Benutzer sendet eine Anfrage an https://mysite.com/friends
  3. Gateway delegiert gemäß der von uns beschriebenen Logik die Anforderung:
    3.1 Eine Nachricht (Anforderungsparameter, Header, Verbindungsinformationen usw.) wird an die RabbitMQ-Warteschlange gesendet
    3.2. Microservice lauscht dieser Warteschlange und verarbeitet eine neue Anforderung
    3.3. Microservice sendet eine Antwort an die Warteschlange
    3.4. Das Gateway wartet auf eine Antwortwarteschlange und erhält eine Antwort von einem Mikrodienst
    3.5. Gateway sendet eine Antwort an den Client
  4. Der Benutzer erhält eine Antwort.

Wir schreiben einen 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(); 

Wie es funktionieren wird:


  1. Der Microservice wird gestartet und beginnt mit dem Abhören der Anforderungswarteschlange, in die das Gateway schreibt.
  2. Der Microservice empfängt die Anfrage, verarbeitet sie und durchläuft alle verfügbaren Middlewares
  3. Microservice sendet eine Antwort an Gateway
    3.1. Die Nachricht wird an die RabbitMQ-Warteschlange gesendet (Header, HTTP-Code-Antworttext)
    3.2. Gateway hört auf diese Warteschlange, empfängt eine Nachricht und findet einen Client, an den es eine Antwort senden muss
    3.3 Gateway sendet eine Antwort an den Client

Monolith-Migration zur Microservice-Architektur


Angenommen, wir haben bereits eine Express-Anwendung und möchten sie auf Microservices portieren.


Es sieht so aus:


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

Wir wollen 2 Endpunkte daraus machen: / friends und / status. Was müssen wir dafür tun?


  1. Ziehen Sie die Geschäftslogik in einen Microservice
  2. Implementieren Sie die Delegierung von Anforderungen für diese beiden Endpunkte an den Microservice
  3. Erhalten Sie eine Antwort vom Microservice
  4. Antwort an Client senden

Im obigen Beispiel haben wir beim Erstellen des Mikroservices für Benutzer zwei Methoden implementiert: / friends und / status, die dasselbe tun wie unser Monolith.


Um Anfragen vom Gateway an den Microservice weiterzuleiten, verwenden wir dasselbe Paket, indem wir die Middleware mit unserer Express-Anwendung verbinden:


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

Dies funktioniert genauso wie im obigen Beispiel, in dem wir ein sauberes Gateway geschrieben haben. In diesem Beispiel besteht der einzige Unterschied darin, dass nicht das Gateway Anforderungen akzeptiert, sondern ein in Express geschriebener Monolith.


Was weiter


  1. RPC (Remote Action Call) von einem Microservice zu einem Monolithen / Gateway (z. B. zur Autorisierung)
  2. Kommunizieren Sie zwischen Microservices über RabbitMQ-Warteschlangen, um weitere Informationen zu erhalten, da jeder Microservice über eine eigene Datenbank verfügt

Ich habe dies bereits in dem Artikel „Lernen, zwischen Microservices auf Node.js über RabbitMQ zu kommunizieren“ gesagt.


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


All Articles