NestJS bietet hervorragende Unterstützung für die Entwicklung von Microservices-Architekturen durch ein umfassendes Set von Tools und Abstraktionen, die die Komplexität verteilter Systeme reduzieren.
In einer Microservices-Architektur wird eine Anwendung in kleine, unabhängige Services aufgeteilt, die über Netzwerkschnittstellen kommunizieren. NestJS unterstützt dieses Paradigma durch:
@Module({
imports: [
ClientsModule.register([
{
name: 'USER_SERVICE',
transport: Transport.TCP,
options: { host: 'localhost', port: 8877 }
}
])
]
})
export class AppModule {}NestJS verwendet Message Patterns für die Kommunikation zwischen Services:
// Service (Provider)
@Controller()
export class UserController {
@MessagePattern({ cmd: 'get_user' })
getUser(data: { id: number }) {
return this.userService.findById(data.id);
}
@EventPattern('user_created')
handleUserCreated(data: Record<string, unknown>) {
console.log('User created:', data);
}
}
// Client
@Injectable()
export class ApiService {
constructor(
@Inject('USER_SERVICE') private client: ClientProxy
) {}
async getUser(id: number) {
return this.client.send({ cmd: 'get_user' }, { id });
}
emitUserCreated(userData: any) {
this.client.emit('user_created', userData);
}
}NestJS unterstützt verschiedene Transport-Mechanismen:
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.TCP,
options: { host: 'localhost', port: 8877 }
});const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.REDIS,
options: {
host: 'localhost',
port: 6379,
}
});const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.NATS,
options: {
servers: ['nats://localhost:4222']
}
});Für dynamische Service-Erkennung können Sie Service Discovery Pattern implementieren:
@Injectable()
export class ServiceRegistry {
private services = new Map<string, string>();
registerService(name: string, url: string) {
this.services.set(name, url);
}
getService(name: string): string | undefined {
return this.services.get(name);
}
}Das Circuit Breaker Pattern verhindert Kaskadenausfälle:
@Injectable()
export class CircuitBreakerService {
private failures = 0;
private readonly threshold = 5;
private state: 'CLOSED' | 'OPEN' | 'HALF_OPEN' = 'CLOSED';
async callService<T>(serviceCall: () => Promise<T>): Promise<T> {
if (this.state === 'OPEN') {
throw new Error('Circuit breaker is OPEN');
}
try {
const result = await serviceCall();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private onSuccess() {
this.failures = 0;
this.state = 'CLOSED';
}
private onFailure() {
this.failures++;
if (this.failures >= this.threshold) {
this.state = 'OPEN';
}
}
}Für verteiltes Logging verwenden Sie Correlation IDs:
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const correlationId = uuidv4();
const request = context.switchToHttp().getRequest();
request.correlationId = correlationId;
return next.handle().pipe(
tap(() => {
this.logger.log(`Request processed: ${correlationId}`);
})
);
}
}Ein API Gateway fungiert als zentrale Schnittstelle:
@Controller('api')
export class GatewayController {
constructor(
@Inject('USER_SERVICE') private userService: ClientProxy,
@Inject('ORDER_SERVICE') private orderService: ClientProxy
) {}
@Get('users/:id')
async getUser(@Param('id') id: string) {
return this.userService.send({ cmd: 'get_user' }, { id });
}
@Get('orders/:userId')
async getUserOrders(@Param('userId') userId: string) {
return this.orderService.send({ cmd: 'get_orders' }, { userId });
}
@Get('users/:id/profile')
async getUserProfile(@Param('id') id: string) {
const user = await firstValueFrom(
this.userService.send({ cmd: 'get_user' }, { id })
);
const orders = await firstValueFrom(
this.orderService.send({ cmd: 'get_orders' }, { userId: id })
);
return { user, orders };
}
}Die Microservices-Architektur mit NestJS ermöglicht es, skalierbare und wartbare verteilte Systeme zu entwickeln, wobei jeder Service klar definierte Verantwortlichkeiten hat und unabhängig entwickelt werden kann.