1. 微服务架构概述

1.1 单体架构 vs 微服务架构

在深入 NestJS 微服务之前,必须理解两种架构范式的根本差异。单体架构(Monolithic Architecture)将所有功能模块打包在同一个进程中运行,而微服务架构(Microservices Architecture)则将系统拆分为多个独立部署的服务单元。

对比维度 单体架构 微服务架构
部署单元 单个 WAR/JAR 包 多个独立进程
模块耦合 高耦合,代码仓库统一 低耦合,独立代码仓库
扩展粒度 整体水平扩展 按服务独立扩展
技术栈 单一语言/框架 多语言异构
故障隔离 单点故障影响全局 故障隔离在单个服务
通信方式 进程内函数调用 网络 RPC/消息队列
关键认知: 单体架构在项目初期开发效率高,但当团队规模超过 10 人、代码行数超过 20 万行时,单体架构的构建速度、部署频率、故障恢复能力会急剧下降。微服务架构正是为解决这些规模化问题而生。
单体架构 vs 微服务架构 对比图 单体架构 用户界面层 业务逻辑层 数据访问层 数据库 单进程 · 单部署单元 · 共享内存 微服务架构 用户服务 订单服务 支付服务 库存服务 通知服务 网关服务 多进程 · 独立部署 · 网络通信

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 微服务架构核心组件 客户端层(ClientProxy) 传输器层(TCP / Redis / RabbitMQ / Kafka / gRPC) 服务层(@MessagePattern / @EventPattern) 请求-响应模式 @MessagePattern() + send() 事件驱动模式 @EventPattern() + emit() 依赖反转注入 自定义 Provider + 接口抽象

快速示例: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();