1. 微服务架构概述
1.1 单体架构 vs 微服务架构
在深入 NestJS 微服务之前,必须理解两种架构范式的根本差异。单体架构(Monolithic Architecture)将所有功能模块打包在同一个进程中运行,而微服务架构(Microservices Architecture)则将系统拆分为多个独立部署的服务单元。
| 对比维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 部署单元 | 单个 WAR/JAR 包 | 多个独立进程 |
| 模块耦合 | 高耦合,代码仓库统一 | 低耦合,独立代码仓库 |
| 扩展粒度 | 整体水平扩展 | 按服务独立扩展 |
| 技术栈 | 单一语言/框架 | 多语言异构 |
| 故障隔离 | 单点故障影响全局 | 故障隔离在单个服务 |
| 通信方式 | 进程内函数调用 | 网络 RPC/消息队列 |
关键认知: 单体架构在项目初期开发效率高,但当团队规模超过 10 人、代码行数超过 20 万行时,单体架构的构建速度、部署频率、故障恢复能力会急剧下降。微服务架构正是为解决这些规模化问题而生。
1.2 微服务的优势与挑战
核心优势
- 独立部署与发布: 每个服务可独立构建、测试、部署,不影响其他服务。部署频率可从月级提升到天级甚至小时级。
- 技术异构性: 不同服务可以使用最适合的技术栈。例如,搜索服务用 Elasticsearch,实时推送用 Node.js,数据分析用 Python。
- 故障隔离: 单个服务的内存泄漏或崩溃不会导致整个系统宕机。通过熔断降级机制,可以将故障限制在局部范围。
- 独立扩展: 只对高负载的服务进行水平扩展,而非整体复制。例如,订单服务需要 10 个实例,而用户服务只需要 3 个。
- 团队自治: 每个服务由独立的小团队(2-8 人)负责,团队拥有从需求到上线的完整所有权。
主要挑战
| 挑战领域 | 具体问题 | NestJS 解决方案 |
|---|---|---|
| 网络通信 | 延迟、丢包、序列化开销 | 内置 TCP/REDIS/RMQ 传输器 |
| 数据一致性 | 分布式事务、最终一致性 | 结合消息队列 + Saga 模式 |
| 服务发现 | 动态 IP、负载均衡 | @nestjs/microservices 客户端代理 |
| 监控与排错 | 分布式链路追踪、日志聚合 | 拦截器 + 自定义装饰器 |
| 熔断降级 | 级联故障、雪崩效应 | 本课程核心:依赖反转 + 熔断策略 |
常见误区: 不要为了微服务而微服务。如果团队小于 10 人、业务逻辑简单、变更频率低,单体架构仍然是更务实的选择。微服务架构的分布式复杂性需要成熟的 DevOps 基础设施支撑。
1.3 NestJS 微服务简介
NestJS 提供了业界最优雅的微服务抽象层。它不重新发明通信协议,而是在 Express/Fastify 之上构建了一套 传输器(Transporter) 抽象体系,让开发者可以用一致的编程模型对接不同的底层通信机制。
NestJS 微服务核心概念
- @nestjs/microservices 包:提供微服务基础模块,包括 ClientProxy、微服务装饰器、管道、异常过滤器。
- 传输器(Transporter):支持 TCP、Redis、RabbitMQ、Kafka、gRPC、MQTT 等多种协议。
- 消息模式(Message Pattern):通过 @MessagePattern() 装饰器定义服务端点,类似 HTTP 路由但更灵活。
- 客户端代理(ClientProxy):服务间通信的抽象客户端,支持请求-响应和事件驱动两种模式。
快速示例:NestJS 微服务基础代码
以下代码展示了一个最简单的 NestJS 微服务——服务端通过 @MessagePattern 暴露端点,客户端通过 ClientProxy 发起调用。
// math.service.ts — 微服务端
import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
@Controller()
export class MathController {
@MessagePattern({ cmd: 'sum' })
accumulate(data: number[]): number {
return (data || []).reduce((a, b) => a + b, 0);
}
}
// main.ts — 微服务启动
import { 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: '127.0.0.1', port: 3001 },
},
);
await app.listen();
}
bootstrap();
// client.ts — 客户端调用
import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices';
const client: ClientProxy = ClientProxyFactory.create({
transport: Transport.TCP,
options: { host: '127.0.0.1', port: 3001 },
});
async function callService() {
const result = await client.send<number, number[]>({ cmd: 'sum' }, [1, 2, 3]).toPromise();
console.log('Result:', result); // 输出: Result: 6
}
callService();