Mikroservices in TypeScript: Architektur und fortgeschrittene Praxis

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum TypeScript die ideale Wahl für Mikroservices ist



Moderne verteilte Architekturen erfordern vom Entwickler nicht nur Kenntnisse über Frameworks, sondern auch ein tiefes Verständnis von Interaktionsmustern, Fehlerbehandlung und Datentypisierung. TypeScript wird dank seiner strengen statischen Typisierung und des leistungsstarken Dekoratorsystems zum De-facto-Standard für den Aufbau zuverlässiger Mikroservices. Im Gegensatz zu reinem JavaScript ermöglicht TypeScript das Abfangen von Fehlern bereits zur Kompilierungszeit, was für Systeme mit Dutzenden von Services kritisch ist.



In diesem Artikel werden wir fortgeschrittene Techniken zum Aufbau einer Mikroservice-Architektur mit TypeScript behandeln: von der Organisation einer modularen Struktur auf Basis von NestJS bis hin zur Implementierung der Transaktionsmuster Saga und CQRS. Sie erfahren, wie Sie eine effiziente serviceübergreifende Kommunikation über RabbitMQ und gRPC einrichten, und erhalten fertige Codevorlagen für Produktionslösungen.



1. Mikroservice-Architektur mit NestJS: Vom Monolithen zum verteilten System



NestJS ist ein progressives Framework für Node.js, das sich dank der integrierten Unterstützung für Transports und Dekoratoren ideal für Mikroservice-Architekturen eignet. Betrachten wir, wie man ein Projekt richtig organisiert.



1.1. Grundlegende Mikroservice-Struktur



Jeder Mikroservice sollte ein isoliertes Modul mit klaren Grenzen sein. Beispiel einer minimalen Struktur:



// user-service/src/main.tsimport { NestFactory } from '@nestjs/core';import { MicroserviceOptions, Transport } from '@nestjs/microservices';import { AppModule } from './app.module';

async function bootstrap() { const app = await NestFactory.createMicroservice<MicroserviceOptions>( AppModule, { transport: Transport.TCP, options: { host: '0.0.0.0', port: 3001, }, }, ); await app.listen();}bootstrap();


Der entscheidende Punkt ist die Verwendung von MicroserviceOptions und die strenge Typisierung des Transports. Dies stellt sicher, dass der Compiler beim Wechsel des Protokolls (z. B. von TCP zu Redis) angibt, welche Parameter geändert werden müssen.



1.2. Modulare Organisation und Dependency Injection



Für Produktionssysteme ist es wichtig, Geschäftslogik und Infrastrukturcode zu trennen. Verwenden Sie NestJS-Module, um verwandte Komponenten zu gruppieren:



// user-service/src/user/user.module.tsimport { Module } from '@nestjs/common';import { UserController } from './user.controller';import { UserService } from './user.service';import { DatabaseModule } from '../database/database.module';

@Module({ imports: [DatabaseModule], controllers: [UserController], providers: [UserService], exports: [UserService],})export class UserModule {}


Eine fortgeschrittene Praxis ist die Verwendung von Factory-Providern für die dynamische Konfiguration von Datenbank-Clients oder Nachrichtenwarteschlangen.



2. Saga- und CQRS-Patterns: Verwaltung verteilter Transaktionen



In einer Mikroservice-Architektur können keine traditionellen ACID-Transaktionen verwendet werden. Stattdessen kommen die Patterns Saga (für Datenkonsistenz) und CQRS (für die Trennung von Lese- und Schreiboperationen) zum Einsatz.



2.1. Implementierung des Saga-Patterns in TypeScript



Saga ist eine Abfolge lokaler Transaktionen, bei der jeder Fehler eine kompensierende Aktion auslöst. Betrachten wir ein Beispiel mit Bestellung und Zahlung:



// order-service/src/sagas/create-order.saga.tsimport { Saga, ofType } from '@nestjs/cqrs';import { Observable } from 'rxjs';import { delay, map } from 'rxjs/operators';

export class CreateOrderSaga { @Saga() createOrder = (events$: Observable<any>): Observable<ICommand> => { return events$.pipe( ofType(OrderCreatedEvent), delay(1000), map(event => new ReserveInventoryCommand(event.orderId)), ); };

@Saga() handlePaymentFailure = (events$: Observable<any>): Observable<IComma

Blogs

Buchempfehlungen