Microservices en JavaScript : architecture et pratique avancée

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Microservices en JavaScript : du monolithe au système distribué



Passer d'une application monolithique à une architecture microservices n'est pas seulement un refactoring technique, mais un changement de philosophie de développement. À un niveau avancé de travail avec Node.js, nous sommes confrontés à la nécessité non seulement de diviser le code en modules, mais de créer un système distribué stable, évolutif et tolérant aux pannes. Dans cet article, nous analyserons les décisions architecturales clés et les patterns pratiques qui vous aideront à construire des microservices prêts pour la production en JavaScript.



Les principaux défis auxquels le développeur est confronté : la synchronisation des données entre les services, le maintien de l'intégrité des transactions, la découverte de services et une communication efficace. Une erreur lors de la phase de conception peut entraîner le chaos en production. Voyons comment l'éviter.



1. Communication entre services : RabbitMQ et gRPC



Dans le monde des microservices, le choix du protocole de communication est crucial. Pour Node.js, deux approches sont les plus populaires : la file d'attente de messages asynchrone (RabbitMQ) et le RPC synchrone haute performance (gRPC).



File d'attente asynchrone (RabbitMQ)

Utilisée pour une architecture orientée événements. Le service producteur n'attend pas de réponse, mais publie un événement. Cela réduit le couplage. Considérons un exemple d'envoi d'une commande au service de livraison.



// Service "Commandes" — producteurconst amqp = require('amqplib');

async function publishOrderCreated(order) { const connection = await amqp.connect('amqp://rabbitmq:5672'); const channel = await connection.createChannel(); const exchange = 'order.events'; await channel.assertExchange(exchange, 'topic', { durable: true });

channel.publish(exchange, 'order.created', Buffer.from(JSON.stringify(order)), { persistent: true });

console.log(`[x] Sent order: ${order.id}`); await channel.close(); await connection.close();}

// Appel lors de la création de la commandepublishOrderCreated({ id: '123', userId: '456', amount: 1500 });


Le service consommateur (livraison) s'abonne à la file d'attente :



// Service "Livraison" — consommateurconst amqp = require('amqplib');

async function consumeOrders() { const connection = await amqp.connect('amqp://rabbitmq:5672'); const channel = await connection.createChannel(); const exchange = 'order.events'; await channel.assertExchange(exchange, 'topic', { durable: true });

const q = await channel.assertQueue('', { exclusive: true }); await channel.bindQueue(q.queue, exchange, 'order.created');

channel.consume(q.queue, (msg) => { if (msg.content) { const order = JSON.parse(msg.content.toString()); console.log(`[x] Received order: ${order.id}`); // Logique de création de livraison channel.ack(msg); } });}

consumeOrders();


gRPC synchrone

Pour les scénarios nécessitant une réponse instantanée (par exemple, vérification du solde utilisateur), gRPC offre un typage strict et une vitesse élevée via HTTP/2. Définissons le fichier proto :



// user.protoservice UserService {  rpc GetUserBalance (UserRequest) returns (UserResponse);}

message UserRequest { string user_id = 1;}

message UserResponse { double balance = 1;}


Implémentation du serveur en Node.js :



const grpc = require('@grpc/grpc-js');const protoLoader = require('@grpc/proto-loader');const PROTO_PATH = './user.proto';

const packageDefinition = protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true});const userProto = grpc.loadPackageDefinition(packageDefinition).userservice;

function getBalance(call, callback) { const userId = call.request.user_id; // Simulation de requête à la base de données const balance = userId === '456' ? 5000 : 0; callback(null, { balance });}

const server = new grpc.Server();server.addSe

Blogs

Book Recommendations