Skip to content

Repository files navigation

NestJS 微服务公共模块抽离实战仓库

GitHub stars GitHub forks License: MIT TypeScript NestJS PostgreSQL Redis RabbitMQ BullMQ Java 技术栈转 NestJS 教材

一套可在多个 NestJS 微服务间共享的公共代码仓库(monorepo + shared library)。 包含完整可运行的示例(网关 + 2 个微服务)与详尽的设计文档


目录


一、这个仓库解决什么问题

微服务架构下,最常见的反模式是:每个服务各自重复实现日志、鉴权、数据库连接、DTO、错误码、微服务客户端……

结果:命名不一致、校验规则漂移、错误码各写一套、切换传输层要改所有服务——维护成本随服务数量爆炸。

本仓库演示的标准答案是:把公共能力抽到一个共享库(@app/shared),每个微服务一行接入。

┌─────────────────────────────────────────────────────────────┐
│                      @app/shared(公共库)                       │
│  DTO / 接口 / 错误码 / 消息常量 / guards / filters / interceptors │
│  LoggerModule / DatabaseModule / AuthModule / HealthModule    │
│  ClientsModule(统一微服务客户端) / 链路追踪 / 验证管道             │
└──────────────┬────────────────────┬──────────────────────────┘
               │ SharedModule.forRoot│
       ┌───────▼───────┐    ┌────────▼────────┐    ┌───────────┐
       │  api-gateway   │──▶ │     orders       │    │  billing   │
       │  (HTTP + Redis │    │   (Redis 传输)    │    │  (TCP 传输) │
       │   混合应用)     │    │   订单微服务       │    │  计费微服务  │
       └───────────────┘    └─────────────────┘    └───────────┘

三个示例服务互不相同,却共享同一套公共库——这正是"抽离 + 复用"的最佳演示。


二、仓库结构

nestjs-microservices-shared/
├── README.md                  # 本文档
├── docs/                      # 设计文档(详见"文档导航")
├── apps/
│   ├── api-gateway/           # 网关:HTTP + Redis 微服务(混合应用)
│   ├── orders/                # 订单微服务(Redis 传输)
│   └── billing/               # 计费微服务(TCP 传输)
├── libs/
│   └── shared/                # ★ 公共库 @app/shared
│       └── src/
│           ├── index.ts       # 公共库公开出口(public surface)
│           ├── dto/           # 跨服务 DTO + 校验规则
│           ├── interfaces/    # 领域模型 / 用户 / 调用协议
│           ├── constants/     # 错误码 / 消息模式 / DI token
│           ├── modules/       # logger / database / auth / health
│           ├── microservices/ # 统一客户端封装
│           ├── filters/       # 全局异常过滤器
│           ├── interceptors/  # 响应转换 / 链路追踪 / 日志
│           ├── pipes/         # 统一验证管道
│           └── utils/         # 请求上下文(AsyncLocalStorage)
├── nest-cli.json              # monorepo 工程配置
├── tsconfig.json              # 路径映射 @app/shared
├── docker-compose.yml         # 本地基础设施(Redis)
└── .env.example               # 环境变量模板

三、快速开始

# 1. 安装依赖
npm install

# 2. 启动基础设施(Redis)
docker compose up -d

# 3. 复制环境变量模板
cp .env.example .env

# 4. 分别启动三个服务(各自一个终端)
npm run start:dev:orders    # Redis 传输微服务
npm run start:dev:billing   # TCP 传输微服务
npm run start:dev:gateway   # 网关(HTTP + Redis)

# 5. 验证
curl http://localhost:3000/health          # 健康检查(公开)
curl -X POST http://localhost:3000/orders \
     -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer <token>'   \
     -d '{"items":[{"sku":"A1","unitPrice":100,"quantity":2}]}'

需要真实数据库时:取消 docker-compose.yml 中 postgres 的注释,并把 apps/*/app.module.tsSharedModule.forRoot({ database: { type: 'memory' } }) 替换为 { type: 'postgres', host: ..., ... },再接入 TypeORM(见 docs/03)。


四、核心思路(30 秒版)

  1. exports 是共享的地基——NestJS 模块默认单例,exports 出去的 provider 在所有调用方间共享同一实例。
  2. @Global() 让基础设施免导入——日志/鉴权/配置做成全局模块,任何服务直接注入。
  3. 动态模块 forRoot/forFeature 让"一套代码、每服务一配置"——同一公共模块,各服务传入自己的数据库/密钥/租户配置。
  4. 传输层封装 ClientsModule 让业务不感知 broker——Redis/Kafka/gRPC 切换只改一处。
  5. 常量集中(message-patterns.ts)+ DTO 共享 + 错误码统一——跨服务契约单一事实来源,编译期可查。

五、文档导航

文档 内容
docs/01-architecture-overview.md 架构总览、抽离方式的横向对比(monorepo 库 vs npm 包 vs submodule)、如何选型
docs/02-shared-library-design.md 共享库内部如何分层、公开面如何收敛、演进与版本化策略
docs/03-module-fundamentals.md exports / @Global / 动态模块 / 自定义 provider 的深度讲解
docs/04-microservice-abstractions.md 微服务传输层抽象、请求-响应 vs 事件、超时重试、链路透传
docs/05-advanced-features.md NestJS 高级特性全景清单(含示例与适用场景)
docs/06-go-live-checklist.md 上线清单、迁移步骤、生产注意事项
docs/07-lifecycle-hooks.md 生命周期钩子总结(启动序/关闭序/践行示例)
docs/08-commit-convention.md Git 提交规范(commitlint + husky + commitizen 配置说明)
docs/09-prisma-quickstart.md PrismaClient 方法全览 + 事务两种形态 + 与仓库 TypeORM 对照
docs/10-prisma-relations-indexes.md Prisma 关联查询(include/select/中间表/原生 JOIN)与索引优化(@@index/EXPLAIN)
docs/09-typeorm-vs-prisma.md TypeORM 与 Prisma 双 ORM 对照:范式/选型/接入/坑(含 Prisma 7 迁移)

六、示例包含的高级特性清单

仓库代码通过真实可运行的示例覆盖了以下 NestJS 高级特性:

# 特性 示例位置
1 Monorepo 共享库 + tsconfig paths nest-cli.jsontsconfig.json
2 动态模块 forRoot/forRootAsync/forFeature shared/modules/*/.*.module.ts
3 @Global() 全局模块 LoggerModuleSharedModuleAuthModule
4 自定义 provider(useValue/useFactory/useClass) DatabaseModuleClientsModule
5 全局守卫 + 元数据(APP_GUARD) JwtAuthGuardRolesGuard + @Roles/@Public
6 参数装饰器(createParamDecorator) @CurrentUser()
7 全局管道(class-validator) SharedValidationPipe
8 全局过滤器 / 拦截器 AllExceptionsFilterTransform/RequestId/LoggingInterceptor
9 AsyncLocalStorage 请求上下文(链路追踪) utils/request-context.ts
10 微服务多种传输(Redis + TCP)+ 混合应用 apps/*/main.ts
11 @MessagePattern / @EventPattern(请求-响应 vs 事件) orders/billing 控制器
12 RpcException 业务错误 + 错误码映射 billing.controller.ts + error-codes.ts
13 生命周期钩子 OnModuleInit / OnApplicationShutdown orders.service.tsDatabaseService
14 健康检查 @nestjs/terminus HealthController
15 配置 @nestjs/config ConfigModule + config/configuration.ts
16 聚合模块一行接入 SharedModule.forRoot(...)
17 幂等去重(Redis SET NX EX)+ 防重复下单/扣款 IdempotencyService + orders/billing
18 分布式锁(SET NX PX + Lua 原子释放 + 看门狗自动续期) DistributedLockService + PaymentSagaService
19 支付 Saga:两步支付 + 失败自动补偿(退款+取消) apps/api-gateway/src/saga/payment-saga.service.ts
20 Outbox 可靠事件(先持久化再投递,失败重试进死信) OutboxService + OutboxModule
21 Commit 规范(commitlint + husky + commitizen) .commitlintrc.json.husky/
22 任务队列 BullMQ(延迟任务/自动取消/重试) QueueModuleOrderTimeoutProcessor
23 熔断器 @CircuitBreaker(Resilience4j 风格状态机 + fallback) circuit-breaker/ + billing.confirmPayment
24 RabbitMQ 点对点队列(手动 ack / requeue,与 Redis 广播对比) Transport.RMQ + orders.main.ts、RMQ 客户端
25 混合应用生命周期修复 await app.init() apps/*/main.ts(注释讲解坑)
26 TypeORM + PostgreSQL 真实存储层 @nestjs/typeorm + OrderEntity
27 乐观锁 @VersionColumn + 并发冲突拦截(409) orders.updateStatus(WHERE version + affected 判定)
28 数据库迁移管理(migration:run/generate/revert) typeorm.config.ts + src/migrations/
29 QueryBuilder 动态条件查询(对标 MyBatis 动态 SQL) orders.findAll 分页查询
30 声明式事务 @Transactional + @TransactionManager(对标 Spring) transaction/ + orders.doCreate
31 读写分离(多 DataSource + slave 只读副本) DatabaseModule.replicas + @InjectDataSource('slave')
32 注解族 @Retryable(指数退避)/ @Cacheable / @Idempotent decorators/ + orders/billing 挂载
33 接口限流 @nestjs/throttler + @Throttle/@SkipThrottle 网关全局 + pay 路由收紧(3/10s)
34 定时任务 @nestjs/schedule @Cron(对标 @Scheduled/Quartz) orders.reconciliationScan
35 Prisma 7(schema-first ORM)对照演示 + driver adapter apps/orders/src/prisma-demo/ + prisma/schema.prisma
36 Prisma $transaction 数组式原子事务(双写成对) prismaDemoService.createOrder + prisma_audit_log

七、如何把公共库抽到独立 npm 包

monorepo 适合代码同仓、快速迭代;当共享代码需要被多个独立仓库消费或严格版本化时,把 libs/shared 提取为私有包:

# 方案 A:独立发布(私有 registry / Verdaccio / GitHub Packages)
cd libs/shared
npm run build            # 产出 dist
npm publish --registry http://your-private-registry

# 各微服务安装
npm install @company/shared@^2.1.0
# 方案 B:pnpm workspace 本地链接(无 registry)
# 根 pnpm-workspace.yaml
packages:
  - libs/shared
  - apps/*
# 微服务引用
pnpm add @company/shared --filter nginx-gateway

采用 npm 包方案后,index.ts 的公开面就成为npm 包稳定 API,务必配合语义化版本 + 破坏性变更的 BREAKING CHANGE 说明(详见 docs/02)。


许可证

MIT

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages