3、微服务通信基础:NestJS微服务传输层(TCP、Redis、RabbitMQ、Kafka)、消息模式与事件驱动
微服务架构的核心在于服务间的通信。NestJS 提供了一套抽象化的微服务传输层,允许开发者在不改变业务逻辑的前提下,切换底层通信协议。本章将深入剖析 NestJS 支持的四种主要传输层(TCP、Redis、RabbitMQ、Kafka),并讲解消息模式与事件驱动架构的设计原则。
3.1 传输层核心概念
NestJS 微服务通过 传输层(Transport Layer) 实现进程间通信。每个传输层都遵循相同的 ClientProxy / Microservice 接口,使得业务代码与底层协议解耦。
| 传输层 | 通信方式 | 持久化 | 适用场景 |
|---|---|---|---|
| TCP | 点对点 Socket | 无 | 内部高吞吐、低延迟、简单拓扑 |
| Redis | 发布/订阅 | 无(默认) | 轻量级广播、缓存集成 |
| RabbitMQ | AMQP 队列/交换器 | 支持(队列持久化) | 可靠消息、复杂路由、工作队列 |
| Kafka | 日志分区/消费者组 | 支持(日志持久化) | 高吞吐事件流、日志聚合、数据管道 |
3.2 传输层配置与代码示例
3.2.1 TCP 传输
TCP 是 NestJS 默认的微服务传输层,无需额外依赖。适用于内部服务间的高效 RPC 调用。
// main.ts - TCP 微服务端
import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } 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();
// 客户端调用
import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices';
const client: ClientProxy = ClientProxyFactory.create({
transport: Transport.TCP,
options: { host: 'localhost', port: 3001 },
});
// 发送消息
client.send('get_user', { id: 1 }).subscribe(result => {
console.log(result);
});
3.2.2 Redis 传输
基于 Redis 的发布/订阅机制,适合广播通知或轻量级事件总线。需要安装 redis 包。
// main.ts - Redis 微服务端
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.REDIS,
options: {
host: 'localhost',
port: 6379,
},
},
);
3.2.3 RabbitMQ 传输
RabbitMQ 提供丰富的交换器类型(direct、topic、fanout、headers),支持消息确认、死信队列等高级特性。需要安装 amqplib 和 @nestjs/microservices。
// main.ts - RabbitMQ 微服务端
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.RMQ,
options: {
urls: ['amqp://localhost:5672'],
queue: 'user_queue',
queueOptions: {
durable: true, // 持久化队列
},
},
},
);
3.2.4 Kafka 传输
Kafka 适合高吞吐事件流场景,支持消费者组、分区重平衡。需要安装 kafkajs。
// main.ts - Kafka 微服务端
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.KAFKA,
options: {
client: {
brokers: ['localhost:9092'],
},
consumer: {
groupId: 'user-consumer-group',
},
},
},
);
3.3 消息模式:请求-响应 vs 事件驱动
NestJS 微服务支持两种核心消息模式:请求-响应(Request-Response) 和 事件驱动(Event-Driven)。理解两者的区别是设计健壮微服务的基础。
| 特性 | 请求-响应 | 事件驱动 |
|---|---|---|
| 通信方向 | 点对点,一对一 | 发布/订阅,一对多 |
| 耦合度 | 高(调用方依赖被调用方) | 低(发布者不关心消费者) |
| 超时处理 | 需要显式超时 | 无需等待响应 |
| 典型场景 | 查询用户信息、下单验证 | 订单创建通知、日志收集 |
| NestJS 装饰器 | @MessagePattern() |
@EventPattern() |
client.send() 并返回 Observable,调用方会等待结果;事件驱动模式使用 client.emit(),调用方立即返回,不等待消费者处理完成。
3.4 事件驱动架构与 NestJS 实现
事件驱动架构(EDA)通过事件总线解耦服务,每个服务独立发布和订阅事件。NestJS 通过 @EventPattern() 和 client.emit() 原生支持该模式。
// 事件发布者(订单服务)
@Injectable()
export class OrderService {
constructor(@Inject('EVENT_BUS') private client: ClientProxy) {}
createOrder(orderDto: CreateOrderDto) {
// 业务逻辑...
this.client.emit('order_created', {
orderId: '123',
userId: 456,
amount: 99.99,
});
}
}
// 事件消费者(通知服务)
@Controller()
export class NotificationController {
@EventPattern('order_created')
handleOrderCreated(data: Record<string, unknown>) {
console.log('发送通知:', data);
// 发送邮件、短信等
}
}
3.5 混合传输与网关集成
在实际项目中,一个微服务可能同时暴露多种传输层。例如,对外提供 HTTP API(REST),对内使用 RabbitMQ 进行事件广播。NestJS 支持在同一个应用中混合使用多种传输策略。
// 混合服务示例:同时支持 HTTP 和 RabbitMQ
@Controller()
export class HybridController {
constructor(
private readonly userService: UserService,
@Inject('RABBIT_CLIENT') private readonly rabbitClient: ClientProxy,
) {}
@Post('users')
async createUser(@Body() dto: CreateUserDto) {
const user = await this.userService.create(dto);
// 通过 RabbitMQ 广播事件
this.rabbitClient.emit('user_created', user);
return user;
}
@MessagePattern('get_user_by_id')
async getUserById(@Payload() id: number) {
return this.userService.findById(id);
}
}
@Inject() token,避免依赖注入冲突。同时,不同传输层的超时、重试策略应独立配置。
3.6 传输层对比与选型决策
下表从运维复杂度、吞吐量、可靠性三个维度对比四种传输层,帮助你在架构设计时做出合理选择。
| 维度 | TCP | Redis | RabbitMQ | Kafka |
|---|---|---|---|---|
| 运维复杂度 | 低(无中间件) | 低(Redis 常见) | 中(需管理交换器/队列) | 高(需管理 ZK/KRaft、分区) |
| 吞吐量 | 高(10万+/s) | 中(受限于 Redis 单线程) | 中(5-10万/s) | 极高(百万+/s) |
| 消息可靠性 | 低(无持久化) | 低(Pub/Sub 无确认) | 高(ACK、持久化、死信) | 高(ISR、日志复制) |
| 消息顺序 | 保证(单连接) | 不保证 | 单队列保证 | 分区内保证 |
| 典型场景 | 内部 RPC、实时查询 | 广播通知、缓存失效 | 任务队列、可靠事件 | 事件溯源、日志流 |
3.7 本章小结
NestJS 的微服务传输层抽象使得开发者可以灵活选择底层通信协议,而无需修改业务逻辑。请求-响应模式适合同步查询,事件驱动模式适合异步解耦。在实际架构中,应根据吞吐量、可靠性、运维成本综合选型,并善用混合传输策略构建健壮的微服务系统。