跳到主要内容

架构

定位:为什么是补充而非替代​

传统后端(Spring、Laravel)建立在“请求-响应”同步模型之上,擅长业务 CRUD、事务一致性、权限体系与报表计算,是业务数据的唯一可信来源(System of Record)。但在以下场景中,同步模型与运行时特性会成为瓶颈:

  • 海量长连接:WebSocket 需要单实例维持数万连接,Java/PHP 的线程模型与内存开销成本高;Node.js 事件驱动 + 非阻塞 I/O 天然适合 I/O 密集的长连接场景
  • 聚合查询(BFF):一个页面需要调用多个下游服务拼装数据,Node.js 的异步并发模型与 GraphQL 生态(Apollo)契合度高
  • 实时消息编排:站内信、订阅推送、事件广播等需要“连接态 + 事件流”的场景

因此 Node.js 服务的定位是:承接传统后端不擅长的实时通信与聚合查询,共享同一套鉴权与安全基线,融入同一个微服务体系。

单向数据原则:Node.js 服务不直接读写业务数据库,所有业务数据通过 Spring 服务的内部 REST API 获取;Node.js 只做聚合、转换与实时分发。业务写操作一律回到传统后端。

能力边界​

场景传统后端(Spring/Laravel)Node.js 服务
业务 CRUD / 事务 / 数据持久化✔️ 唯一数据源❌ 不承接
用户体系 / 令牌签发 / 权限定义✔️❌ 仅校验令牌
WebSocket 长连接 / 实时推送❌✔️ 核心职责
SSE 服务端单向推送⚠️ 可实现但长连接成本高✔️
聚合查询(GraphQL BFF)⚠️ 可实现但编排成本高✔️ 核心职责
事件驱动的通知编排⚠️✔️
CPU 密集计算(报表 / 导出 / 图像处理)✔️❌ 单线程事件循环不适用
边界红线
  • Node.js 服务不得签发认证令牌,令牌统一由传统后端认证服务签发,Node.js 只做校验(共享密钥或 JWKS 公钥)
  • Node.js 服务不得直接连接业务数据库进行写操作
  • 新增能力前先判断归属:凡是涉及数据一致性的,归传统后端;凡是涉及连接态与聚合的,归 Node.js

技术栈​

类别选型
运行时Node.js LTS(≥ 22)
框架NestJS
HTTP 平台Fastify(@nestjs/platform-fastify)
WebSocketSocket.IO(@nestjs/platform-socket.io)
SSENestJS 内置 @Sse()(@nestjs/common,无额外依赖)
GraphQLApollo Server(@nestjs/apollo + @as-integrations/fastify)
语言TypeScript
认证JWT(@nestjs/jwt,ES256 公钥验签,令牌由传统后端签发)
参数校验class-validator + class-transformer
安全头 / CSRF框架内置 useSecurityHeaders() / enableCsrfProtection()
限流@nestjs/throttler
缓存 / 广播Redis(ioredis + @socket.io/redis-adapter)
消息队列Kafka(@nestjs/microservices / kafkajs)
日志nestjs-pino(pino,Fastify 原生日志器)
健康检查@nestjs/terminus
单元测试Vitest
代码检查ESLint
部署Docker

分层结构​

NestJS 以 模块(Module) 为组织单元,模块内按职责拆分控制器、服务、网关与解析器:

  • controller:HTTP 端点,承载少量无法被 GraphQL 覆盖的 REST 端点(如健康检查、回调接收)与 SSE 推送端点(@Sse())
  • gateway:WebSocket 网关,管理连接生命周期、事件订阅与推送
  • resolver:GraphQL 解析器,编排查询与字段级数据获取
  • service:业务编排,调用下游 Spring 服务、读写缓存、发布事件
  • provider:横切能力(Guard / Interceptor / Pipe / Filter),HTTP、WebSocket、GraphQL 三种上下文复用同一套(SSE 属 HTTP 上下文)

单向依赖:入口层(controller / gateway / resolver)→ service → 下游客户端,禁止反向引用;横切 provider 可作用于任意入口。

快速开始​

初始化项目​

pnpm add -g @nestjs/cli
nest new realtime-service --strict
cd realtime-service

启用 Fastify​

pnpm add @nestjs/platform-fastify
// main.ts
import { NestFactory } from '@nestjs/core';
import {
FastifyAdapter,
NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
await app.listen(process.env.PORT ?? 3000, '0.0.0.0');
}
bootstrap();

安装核心能力​

pnpm add @nestjs/websockets @nestjs/platform-socket.io

pnpm add @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/fastify graphql

pnpm add @nestjs/config @nestjs/jwt class-validator class-transformer @nestjs/throttler
Fastify 平台差异

切换 Fastify 后,Nest 的 HTTP provider 变为 Fastify,依赖 Express 的中间件与生态包不再可用,需使用 Fastify 等价物:安全头 → 框架内置 useSecurityHeaders()、@apollo/server → 搭配 @as-integrations/fastify、压缩 → @fastify/compress。

技术运用​

本节是技术栈总览。

环境​

  • Node.js:运行时,使用 Active LTS 版本(≥ 22)
  • pnpm:依赖管理与脚本执行

基础技术​

  • NestJS:渐进式 Node.js 框架,提供模块化架构、依赖注入容器与装饰器元数据,统一组织控制器、网关与解析器
  • TypeScript:为 JS 提供静态类型,NestJS 的依赖注入与装饰器元数据建立在 TS 之上
  • RxJS:NestJS 内置的响应式编程库,用于事件流与异步编排

框架与驱动​

包名作用
@nestjs/coreNest 核心:DI 容器、模块系统
@nestjs/platform-fastifyFastify HTTP 适配器
@nestjs/websockets + @nestjs/platform-socket.ioWebSocket 网关(Socket.IO 平台)
@nestjs/graphql + @nestjs/apolloGraphQL 模块(Apollo 驱动)
@apollo/server + @as-integrations/fastifyApollo Server 5 及其 Fastify 集成
@nestjs/microservices微服务传输层(Kafka 等)
@nestjs/http-client内部 REST 客户端(基于 Node.js 内置 fetch,命名客户端)

工具库​

包名作用
ioredisRedis 客户端(缓存、限流存储、Socket.IO 广播适配)
@socket.io/redis-adapterSocket.IO 多实例广播适配器
nestjs-pino结构化日志(pino)
dataloaderGraphQL N+1 查询批处理