Microservices en TypeScript : architecture et pratique de A à Z
\nDans le développement web moderne, l'architecture monolithique cède la place à des microservices flexibles et évolutifs. TypeScript, avec son typage strict et ses outils puissants, est devenu le langage idéal pour construire de tels systèmes. Dans cet article, nous allons voir comment concevoir et implémenter des microservices en TypeScript, en utilisant le framework populaire NestJS, le courtier de messages RabbitMQ et la conteneurisation Docker.
1. Fondamentaux de l'architecture microservices en TypeScript
\nL'architecture microservices consiste à diviser une application en services indépendants et faiblement couplés. Chaque service est responsable de sa propre logique métier (par exemple, gestion des utilisateurs, traitement des commandes, paiements) et peut être développé, déployé et mis à l'échelle séparément.
\n\nPourquoi TypeScript ?
\n- \n
- Typage : Des erreurs à la compilation, pas à l'exécution. Particulièrement important lors de l'interaction de multiples services via le réseau. \n
- Interfaces et types : Permettent de définir strictement les contrats API (par exemple, DTO pour les requêtes/réponses). \n
- JavaScript moderne : TypeScript se compile en JS pur, fonctionnant sous Node.js. \n
Considérons un exemple simple de DTO strictement typé pour un microservice d'utilisateurs :
\n\n// user.dto.ts\nexport interface CreateUserDto {\n readonly email: string;\n readonly password: string;\n readonly name: string;\n}\n\nexport interface UserResponse {\n id: string;\n email: string;\n name: string;\n createdAt: Date;\n}\n\nLors du transfert de données entre services (via HTTP ou RabbitMQ), TypeScript garantit que la structure de l'objet correspond à celle attendue. Cela réduit considérablement le nombre de bugs.
\n\n2. Implémentation d'un microservice avec NestJS
\nNestJS est un framework progressif pour Node.js qui prend en charge nativement l'architecture microservices. Il fournit des transporteurs pour TCP, Redis, RabbitMQ, Kafka et gRPC.
\n\nCréons un microservice de base pour la gestion des utilisateurs en utilisant le transport RabbitMQ.
\n\nÉtape 1 : Installation des dépendances
\nnpm install --save @nestjs/core @nestjs/common @nestjs/microservices\nnpm install --save amqplib amqp-connection-manager\n\nÉtape 2 : Création du module principal et du contrôleur
\n// user.controller.ts\nimport { Controller } from '@nestjs/common';\nimport { MessagePattern, Payload } from '@nestjs/microservices';\nimport { CreateUserDto, UserResponse } from './user.dto';\n\n@Controller()\nexport class UserController {\n @MessagePattern('user.create')\n async createUser(@Payload() data: CreateUserDto): Promise<UserResponse> {\n // Logique de création d'utilisateur en base de données ici\n console.log('Création d\'utilisateur :', data);\n return {\n id: 'uuid-123',\n email: data.email,\n name: data.name,\n createdAt: new Date(),\n };\n }\n}\n\nÉtape 3 : Configuration du fichier principal pour fonctionner en mode microservice
\n// main.ts\nimport { NestFactory } from '@nestjs/core';\nimport { MicroserviceOptions, Transport } from '@nestjs/microservices';\nimport { AppModule } from './app.module';\n\nasync function bootstrap() {\n const app = await NestFactory.createMicroservice<MicroserviceOptions>(\n AppModule,\n {\n transport: Transport.RMQ,\n options: {\n urls: ['amqp://localhost:5672'],\n queue: 'user_queue',\n queueOptions: {\n durable: false,\n },\n },\n },\n );\n await app.listen();\n console.log('Microservice utilisateurs démarré');\n}\nbootstrap();\n\nAinsi, notre service se connecte à RabbitMQ et écoute la file d'attente user_queue. Tout autre service (par exemple, le service de commandes