NATS JetStream 消息集群生产运维与灾难恢复
NATS 提供轻量、低延迟的发布订阅和请求响应,JetStream 在其上增加持久化、复制、Consumer、重放和工作队列能力。生产系统必须理解 Core NATS 与 JetStream 的差异、Subject 设计、确认语义、流复制、存储、集群 Quorum、跨地域拓扑和灾难恢复。
消息系统的“发送成功”不一定代表业务处理完成。必须结合 Publisher Ack、Stream 复制、Consumer Ack、幂等和业务事务定义端到端可靠性。
一、Core NATS 与 JetStream
Core NATS 以内存实时传递为主,订阅者不在线时通常不会保留消息;JetStream 将消息写入 Stream,并由 Consumer 按策略消费和确认。
Publisher → Subject → Stream(持久化与复制)
↓
Consumer
↓ Ack/Nak/Term
Worker
不是所有事件都需要持久化。心跳、瞬态状态可用 Core NATS;订单、任务、审计通常需要 JetStream。
二、Subject 设计
Subject 是点分层级名称,如 orders.created.cn。设计原则:
- 体现业务域、事件和版本;
- 避免把用户敏感信息放入 Subject;
- 使用通配符但控制订阅范围;
- 区分命令、事件与请求响应;
- 预留 Schema 演进;
- 防止无限高基数 Subject。
权限可按 Subject 限制 Publish/Subscribe,因此命名也是安全边界。
三、Stream 配置
Stream 将一个或多个 Subject 映射到存储。核心参数:
- Storage:Memory/File;
- Replicas:副本数;
- Retention:Limits/Interest/WorkQueue;
- Max Age/Bytes/Msgs;
- Discard Policy;
- Duplicate Window;
- Placement 与节点标签。
nats stream add ORDERS \
--subjects 'orders.>' \
--storage file \
--replicas 3 \
--retention limits \
--max-age 168h
四、复制与 Quorum
R=3 Stream 可容忍一个副本节点故障并保持多数派;R=5 可容忍两个,但增加写入延迟与存储。副本应跨宿主机/故障域。
副本数不能超过可用 JetStream 节点。只有节点数量,没有正确 Placement 和独立磁盘,也不能形成可靠容灾。
五、Publisher 确认
JetStream Publish Ack 表示消息被 Stream 接受并按复制协议提交,不代表 Consumer 已处理。
应用应:
- 设置超时与重试;
- 使用消息 ID 进行去重;
- 重试保持同一业务 ID;
- 处理“服务端已接收但 Ack 丢失”的不确定状态;
- 监控发布延迟和错误。
六、Consumer 类型
Durable Consumer 保留消费进度;Ephemeral 随订阅生命周期消失。Pull Consumer 便于 Worker 控制批量和背压;Push Consumer 由服务端推送。
生产任务队列通常使用 Durable Pull Consumer,并设置 Ack Policy、Ack Wait、Max Deliver 和 Backoff。
nats consumer add ORDERS WORKERS \
--pull \
--ack explicit \
--deliver all \
--max-deliver 10
七、Ack 与重复投递
显式 Ack 下,未在 Ack Wait 内确认的消息会重投。网络故障、Worker 重启和处理超时都会产生重复。
消费者必须幂等:
- 业务唯一键;
- 数据库唯一约束;
- 幂等记录表;
- 状态机检查;
- Outbox/Inbox 模式。
不要依赖“通常只来一次”。
八、Nak、Term 与 In Progress
- Ack:处理成功;
- Nak:处理失败并按策略重投;
- Term:终止后续重投;
- In Progress:长任务延长处理租约。
无法处理的消息应进入 DLQ/告警流程,而不是无限快速重试。DLQ 可以用 Advisories 或重投达到阈值后的业务处理实现。
九、Retention 策略
LimitsPolicy 按时间/数量/大小保留;InterestPolicy 在所有相关 Consumer 确认后清理;WorkQueuePolicy 适合任务队列,消息由一个 Consumer 路径处理。
选择错误会导致消息过早删除或长期占用磁盘。上线前模拟 Consumer 离线、删除和新增行为。
十、存储与容量
File Storage 需要低延迟可靠磁盘。容量估算包含:
消息速率 × 平均大小 × 保留时间 × 副本数
+ 索引/元数据/碎片/快照余量
监控每个 Stream 消息、字节、首尾序号、存储、消费者积压和磁盘。避免 JetStream 与日志、容器层共用小系统盘。
十一、集群设计
NATS Cluster 提供路由与 JetStream 节点发现。客户端连接多个 URL 或域名,服务器之间 Route 独立于客户端端口。
配置:
- 唯一 Server Name;
- Cluster Name 一致;
- Route 认证与 TLS;
- JetStream Store Directory;
- 节点标签与域;
- 资源限制;
- 监控端口隔离。
十二、Leader 与故障切换
Stream 和 Consumer 有 Leader。Leader 故障后多数派选举新 Leader,期间可能短暂不可用。
nats stream info ORDERS
nats consumer info ORDERS WORKERS
nats server report jetstream
频繁 Leader 变化通常指向网络、磁盘、CPU 停顿或节点不稳定。
十三、Supercluster 与 Leaf Node
Supercluster 连接多个 Cluster,适合地域间路由;Leaf Node 适合边缘、门店和隔离网络向中心汇聚。
JetStream 数据不会因为 Core NATS 路由自动变成跨地域同步。需要 Source/Mirror、Domain 和放置策略,并明确延迟、故障和一致性。
跨地域 Quorum 会受 WAN 延迟影响,通常将复制放在本地故障域,再设计异地复制与恢复。
十四、Mirror 与 Source
Mirror 复制一个 Stream,Source 可聚合一个或多个 Stream。用于迁移、汇聚和灾备时关注:
- 复制延迟;
- Subject 变换;
- 起始序号/时间;
- 删除与保留;
- 目标容量;
- 故障切换后的双写冲突。
异步复制必须纳入 RPO。
十五、Schema 与版本
NATS 不强制消息 Schema,组织应使用 Protobuf/Avro/JSON Schema 等约束。事件包含版本、事件 ID、发生时间、生产者和 Trace ID。
兼容策略:先新增可选字段、消费者先兼容新旧、再升级生产者;避免直接改变字段含义或复用旧 Subject 发布不兼容格式。
十六、安全
使用 TLS、用户/账号隔离、NKey/JWT 或合适认证方式。按 Subject 限制权限,管理与监控端口只在管理网络开放。
不同团队使用 Account 隔离,并通过 Export/Import 显式共享服务或 Stream。不要全员共享管理员凭证。
十七、监控
监控 Server、Route、Gateway/Leaf、连接、订阅、内存、CPU、FD、JetStream 存储、API Error、Stream Replica、Leader、Consumer Pending、Ack Pending、Redelivery 和发布延迟。
只监控 Server Up 不足以发现 Consumer 已积压数百万消息。
十八、备份与恢复
JetStream 可对 Stream 做 Snapshot/Restore,也可采用复制与文件系统级受控备份。必须同时保存配置、账号、JWT/NKey、TLS、Stream/Consumer 定义和应用 Schema。
恢复应在隔离集群验证消息序号、Stream State、Consumer 起点和应用幂等。直接复制正在写入的数据目录可能不一致。
十九、常见故障
发布超时
检查 Stream Leader、Quorum、磁盘、网络、Subject 是否匹配、权限和资源限制。
Consumer 积压
检查处理速率、错误、Ack Wait、重投、下游数据库、批量与并发。增加 Worker 前确认下游承载能力。
重投风暴
处理时间超过 Ack Wait、Worker 崩溃或毒消息。使用 In Progress、Backoff、Max Deliver 和 DLQ。
磁盘快速增长
检查 Retention、Max Age、Consumer Interest、未完成复制、Stream 数和消息大小。
二十、升级
逐节点升级,保持集群和每个 R=3 Stream 多数派。先升级非 Leader 或按官方策略,观察 Route、JetStream、Leader 和业务。版本混跑时间应最小化。
二十一、上线清单
- Core NATS 与 JetStream 使用场景分清;
- Subject、Schema 和权限经过治理;
- Stream 副本跨故障域;
- Publisher 处理不确定 Ack;
- Consumer 幂等并有 DLQ;
- Retention 和容量完成压力测试;
- WAN 拓扑不跨地域强行组成高延迟 Quorum;
- Stream/Consumer/凭证完成恢复演练;
- 节点、Leader、磁盘和积压均有告警。
参考资料
- NATS Documentation:
https://docs.nats.io/ - JetStream:
https://docs.nats.io/nats-concepts/jetstream - Clustering and Replication:
https://docs.nats.io/learn/clustering/