NestJS ma wbudowaną obsługę mikrousług — może działać jako mikrousługa komunikująca się przez różne transporty (TCP, Redis, NATS, RabbitMQ, Kafka, gRPC) zamiast HTTP, używając spójnego, opartego na wiadomościach modelu programowania. Ta sama struktura NestJS (moduły, serwisy, DI) ma zastosowanie; zmienia się tylko transport i wzorce wiadomości.
Tworzenie mikrousługi
// a microservice listens on a transport instead of HTTP
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.TCP, // or REDIS, NATS, RMQ, KAFKA, GRPC
options: { host: "0.0.0.0", port: 3001 },
});
await app.listen();
Wzorce wiadomości vs wzorce zdarzeń
@Controller()
export class MathController {
// REQUEST-RESPONSE: respond to a message and RETURN a result (RPC-style)
@MessagePattern({ cmd: "sum" })
sum(data: number[]): number {
return data.reduce((a, b) => a + b, 0); // the caller awaits this result
}
// EVENT-BASED: react to an event, NO response expected (fire-and-forget)
@EventPattern("order_created")
handleOrderCreated(data: OrderDto) {
this.processOrder(data); // just react; nothing returned
}
}
Dwa style komunikacji: @MessagePattern dla request-response (wywołujący czeka na wynik, jak RPC) i @EventPattern dla zdarzeń (fire-and-forget, niezwiązane — wydawca nie czeka).
Wywoływanie innej mikrousługi (klient)
@Injectable()
export class AppService {
constructor(@Inject("MATH_SERVICE") private client: ClientProxy) {}
async getSum() {
// send() → request-response (returns an Observable of the result)
return this.client.send({ cmd: "sum" }, [1, 2, 3]);
// emit() → fire an event (no response)
this.client.emit("order_created", orderData);
}
}
ClientProxy (skonfigurowany za pomocą ClientsModule) wysyła wiadomości/zdarzenia do innych usług — send() dla request-response, emit() dla zdarzeń.
Aplikacje hybrydowe
// an app can serve HTTP AND connect microservice transports simultaneously
const app = await NestFactory.create(AppModule);
app.connectMicroservice({ transport: Transport.RMQ, options: {...} });
await app.startAllMicroservices();
await app.listen(3000); // HTTP too
Wybór transportu ma znaczenie
TCP → simple direct service-to-service
Redis/NATS → lightweight pub/sub messaging
RabbitMQ/Kafka → robust message queues/streams (durability, retries, decoupling)
gRPC → high-performance, strongly-typed RPC (protobuf)
→ Async message brokers (RMQ/Kafka) give decoupling & resilience; gRPC gives speed+typing.
Dlaczego to ważne
Wbudowana obsługa mikrousług w NestJS jest ważna, ponieważ pozwala na budowanie systemów rozproszonych przy użyciu tej samej znanej struktury NestJS (moduły, providery, DI, dekoratory) podczas zamiany HTTP na transporty oparte na wiadomościach — duża przewaga produktywności i spójności.
Zrozumienie tego jest ważne dla architektury skalowalnych systemów: rozróżnienie między message-pattern (request-response) a event-pattern (fire-and-forget) mapuje się bezpośrednio na fundamentalny wybór komunikacji mikrousług — synchroniczne wywołania RPC versus asynchroniczne, niezwiązane zdarzenia (te ostatnie, za pośrednictwem brokerów wiadomości, zapewniające odporność i luźne sprzężenie, które czynią mikrousługi niezawodnymi).
Wiedzenie, jak tworzyć mikrousługi, definiować procedury obsługi wiadomości/zdarzeń, wywoływać inne usługi za pośrednictwem ClientProxy, budować hybrydowe aplikacje HTTP+mikrousług i wybierać transporty (lekkie pub/sub vs trwałe kolejki jak Kafka/RabbitMQ vs wysokowydajny gRPC) to cenna wiedza na poziomie seniora do projektowania rozproszonych backendów.
Chociaż mikrousługi dodają prawdziwą złożoność (i nie zawsze są właściwym wyborem w porównaniu do monolitu), NestJS czyni implementację czystą i spójną, co czyni ten temat ważnym dla budowania dużych, rozproszonych systemów NestJS.
