Einführung in NestJS Microservices
Die Mikroservices-Architektur hat in den letzten Jahren aufgrund ihrer Flexibilität, Skalierbarkeit und Fähigkeit zur kontinuierlichen Bereitstellung enorm an Beliebtheit gewonnen. NestJS, ein fortschrittliches Node.js-Framework, bietet hervorragende Unterstützung beim Erstellen von Mikroservices. Es ermöglicht Entwicklern, modulare und wartbare Anwendungen zu erstellen, die unabhängig wachsen und skaliert werden können.
In diesem Blogbeitrag werden wir erkunden, wie man eine Mikroservices-Anwendung mit NestJS aufbaut, unterstützt durch ein praktisches Beispiel. Wir behandeln die Grundlagen von NestJS-Mikroservices, richten ein einfaches Projekt ein und implementieren einen Service, der über Kafka zwischen mehreren Mikroservices kommuniziert.
Verständnis von NestJS Microservices
NestJS bietet eine einfache Möglichkeit, Mikroservices zu erstellen, die über verschiedene Transportebenen wie TCP, Redis, NATS und Kafka miteinander kommunizieren können. Das Framework ermöglicht es, Mikroservices mit minimalem Boilerplate-Code zu definieren, sodass Sie sich auf die Geschäftslogik konzentrieren können.
Hauptmerkmale:
- Modularität: Jeder Mikroservice kann unabhängig entwickelt, getestet und bereitgestellt werden.
- Skalierbarkeit: Dienste können je nach Nachfrage skaliert werden.
- Inter-Service-Kommunikation: NestJS bietet verschiedene Optionen für die Kommunikation zwischen Diensten, einschließlich Nachrichtenbroker wie Kafka.
Einrichten eines NestJS-Mikroservices-Projekts
Voraussetzungen
- Node.js auf Ihrem Rechner installiert
- Grundkenntnisse in TypeScript und NestJS
- Apache Kafka installiert oder ein Cloud-Anbieter (z. B. Confluent Cloud) mit Zugriff auf eine Kafka-Instanz
Schritt 1: Erstellen eines neuen NestJS-Projekts
Installieren Sie zuerst die Nest CLI, falls Sie dies noch nicht getan haben:
npm i -g @nestjs/cli
Erstellen Sie ein neues Projekt:
nest new nest-microservices
cd nest-microservices
Schritt 2: Installieren der erforderlichen Pakete
Wir werden @nestjs/microservices und kafkajs für die Kafka-Unterstützung verwenden. Installieren Sie sie mit npm:
npm install @nestjs/microservices kafkajs
Schritt 3: Erstellen von Mikroservices
Für unser Beispiel erstellen wir zwei Mikroservices: Benutzer und Produkte. Jeder wird seine eigenen Daten verwalten und über Kafka kommunizieren.
Erstellen des Benutzer-Mikroservices
- Generieren Sie ein neues Modul und einen neuen Dienst:
nest generate module users nest generate service users - Implementieren Sie im
users.service.tsgrundlegende Benutzerverwaltungsfunktionen: - Erstellen Sie einen Controller, um HTTP-Anfragen zu bearbeiten:
nest generate controller users - Richten Sie in
users.controller.tsEndpunkte ein: - Richten Sie den Mikroservice in der
main.ts-Datei ein:
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private users = [];
createUser(user: { name: string; age: number }) {
this.users.push(user);
return user;
}
findAll() {
return this.users;
}
}
import { Controller, Post, Body, Get } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() user: { name: string; age: number }) {
return this.usersService.createUser(user);
}
@Get()
findAll() {
return this.usersService.findAll();
}
}
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.KAFKA,
options: {
client: {
clientId: 'users-service',
brokers: ['localhost:9092'], // Ersetzen Sie dies durch Ihre Kafka-Broker-Adresse
},
consumer: {
groupId: 'users-consumer', // Eindeutige Gruppen-ID für diesen Verbraucher
},
},
});
await app.listen();
}
bootstrap();
Erstellen des Produkt-Mikroservices
Wiederholen Sie ähnliche Schritte für den Produkt-Mikroservice:
- Generieren Sie das Modul und den Dienst:
nest generate module products nest generate service products - Implementieren Sie den
products.service.ts:import { Injectable } from '@nestjs/common'; @Injectable() export class ProductsService { private products = []; createProduct(product: { name: string; price: number }) { this.products.push(product); return product; } findAll() { return this.products; } } - Richten Sie den Controller für Produkte ein:
nest generate controller products - Richten Sie in
products.controller.tsEndpunkte ein: - Richten Sie den Mikroservice in
main.tsein:
import { Controller, Post, Body, Get } from '@nestjs/common';
import { ProductsService } from './products.service';
@Controller('products')
export class ProductsController {
constructor(private readonly productsService: ProductsService) {}
@Post()
create(@Body() product: { name: string; price: number }) {
return this.productsService.createProduct(product);
}
@Get()
findAll() {
return this.productsService.findAll();
}
}
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.KAFKA,
options: {
client: {
clientId: 'products-service',
brokers: ['localhost:9092'], // Ersetzen Sie dies durch Ihre Kafka-Broker-Adresse
},
consumer: {
groupId: 'products-consumer', // Eindeutige Gruppen-ID für diesen Verbraucher
},
},
});
await app.listen();
}
bootstrap();
Inter-Service-Kommunikation mit Kafka
Um die Kommunikation zwischen dem Benutzer- und dem Produkt-Mikroservice über Kafka zu ermöglichen, richten wir Nachrichtenmuster ein.
Schritt 1: Senden von Nachrichten vom Benutzer-Service an den Produkt-Service
Im Benutzer-Service veröffentlichen wir ein Ereignis in Kafka, wann immer ein Benutzer erstellt wird. Ändern Sie den UsersService, um das Kafka-Publishing zu integrieren:
import { Injectable, Inject } from '@nestjs/common';
import { ClientKafka } from '@nestjs/microservices';
@Injectable()
export class UsersService {
constructor(@Inject('PRODUCTS_SERVICE') private readonly client: ClientKafka) {}
async createUser(user: { name: string; age: number }) {
const createdUser = { name: user.name, age: user.age };
// Benutzer erstellt Ereignis veröffentlichen
await this.client.emit('user_created', createdUser);
return createdUser;
}
// Weitere Methoden...
}
Schritt 2: Abonnieren von Nachrichten im Produkt-Service
Fügen Sie im Produkt-Service einen Kafka-Consumer hinzu, um auf das user_created-Ereignis zu hören:
import { Injectable } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
@Injectable()
export class ProductsService {
// Weitere Methoden...
@MessagePattern('user_created')
handleUserCreated(user: { name: string; age: number }) {
console.log('Neuer Benutzer erstellt:', user);
// Logik zur Verarbeitung neuer Benutzerinformationen...
}
}
Testen der Mikroservices
Nachdem unsere Mikroservices eingerichtet sind, lassen Sie uns diese ausführen:
- Starten Sie den Benutzer-Mikroservice:
cd users npm run start --watch - Starten Sie in einem separaten Terminal den Produkt-Mikroservice:
cd products npm run start --watch - Verwenden Sie ein Tool wie Postman oder curl, um die Endpunkte zu testen.
Um einen Benutzer zu erstellen:
curl -X POST http://localhost:3000/users -H 'Content-Type: application/json' -d '{"name": "John Doe", "age": 30}'
Um alle Benutzer abzurufen:
curl -X GET http://localhost:3000/users
Um ein Produkt zu erstellen:
curl -X POST http://localhost:3001/products -H 'Content-Type: application/json' -d '{"name": "Produkt 1", "price": 100}'
Um alle Produkte abzurufen:
curl -X GET http://localhost:3001/products
Nachrichtenmuster
Mikroservices erkennen sowohl Nachrichten als auch Ereignisse anhand von Mustern. Ein Muster ist ein einfacher Wert, beispielsweise ein literales Objekt oder eine Zeichenfolge. Muster werden automatisch serialisiert und zusammen mit dem Datenanteil einer Nachricht über das Netzwerk gesendet. Auf diese Weise können Nachrichtenversender und -empfänger koordinieren, welche Anfragen von welchen Handlern verarbeitet werden.
Request-Response
Der Request-Response-Nachrichtenstil ist nützlich, wenn Sie Nachrichten zwischen verschiedenen externen Diensten austauschen müssen. Mit diesem Paradigma können Sie sicher sein, dass der Dienst die Nachricht tatsächlich empfangen hat (ohne dass ein manuelles Nachrichtenaus ACK-Protokoll implementiert werden muss). Das Request-Response-Paradigma ist jedoch nicht immer die beste Wahl. Beispielsweise sind Streaming-Transporter, die logbasierte Persistenz verwenden, wie Kafka oder NATS Streaming, darauf optimiert, eine andere Reihe von Problemen zu lösen, die stärker mit einem ereignisgesteuerten Messaging-Paradigma verbunden sind.
Fazit
In diesem Blogbeitrag haben wir die Grundlagen der Erstellung von Mikroservices mit NestJS erkundet. Wir haben zwei Mikroservices, Benutzer und Produkte, entwickelt, die über Kafka kommunizieren. Dieses Beispiel zeigt, wie einfach es ist, skalierbare und wartbare Anwendungen mit NestJS zu erstellen.
Mit NestJS können Sie komplexe Mikroservices-Architekturen aufbauen, die leicht zu verwalten und zu skalieren sind. Die leistungsstarken Funktionen des Frameworks und die Benutzerfreundlichkeit machen es zu einer hervorragenden Wahl für moderne Webanwendungen.
Fühlen Sie sich frei, mit diesem Beispiel zu experimentieren, weitere Funktionen hinzuzufügen und die verschiedenen Transportebenen zu erkunden, die NestJS für Mikroservices bietet!
