连NATS需显式配置重连、凭证和TLS;JetStream需手动初始化上下文并创建流,设对RetentionPolicy、发布带唯一MsgID、订阅用DeliverAll,多goroutine并发publish会导致乱序。

怎么连上NATS服务器,又不被网络抖动搞崩
裸调用 nats.Connect(nats.DefaultURL) 在开发时能跑通,但一上生产就掉线不重连——这不是你的代码问题,是默认配置根本没开重试。
- 必须显式加重连策略:
nats.MaxReconnects(60)、nats.ReconnectWait(2*time.Second)、nats.ReconnectJitter(100*time.Millisecond, time.Second) - 别把密码写死在 URL 里,比如
"nats://user:pass@host:4222";改用nats.UserCredentials("user.creds")加载凭证文件 - 如果启用了 TLS,记得用
"tls://..."协议前缀,且服务端证书要可信,否则Connect会静默失败(不是报错,是卡住)
发出去的消息,为什么消费者收不到
默认 NATS 是纯内存转发,订阅者离线期间发布的消息直接丢弃——这设计没错,但很多人误以为“发了=收到了”。
- 想“不丢”,必须启用 JetStream 并创建流(Stream),光连上 JetStream 不够,得调
js.AddStream()显式声明 - 创建流时,
RetentionPolicy必须设对:jetstream.InterestPolicy(只存活跃订阅者需要的)或jetstream.WorkQueuePolicy(每条只投一次) - 订阅时要用
nats.DeliverPolicy(nats.DeliverAll)才能从头消费;若用DeliverLastPerSubject,重启后可能跳过中间事件
JetStream 发消息重复/乱序,是不是服务端 bug
不是。重复和乱序都源于客户端用法不对,NATS 本身不保证顺序,也不自动去重。
- 去重要生效,发布时必须带 ID:
js.Publish("orders.created", data, nats.WithMsgID("order-123")),ID 得业务唯一(不能是uuid.New()) - 流配置里的
Duplicates: 2*time.Minute是去重窗口,不是保留时间;如果处理耗时超 2 分钟,重复仍会发生 - 多 goroutine 并发调
js.Publish()同一 subject,消息大概率乱序;关键顺序场景,得用单 goroutine + channel 缓冲,或加业务层序列号校验
为什么第一次 js.Publish() panic
因为 JetStream 上下文没提前初始化。NATS 客户端连接后不会自动准备 JetStream 能力,得手动获取 jetstream.Context。
立即学习“go语言免费学习笔记(深入)”;
- 连接后立刻执行:
js, err := jetstream.New(nc),别等到 publish 前才调 - 如果忘了这步,第一次
js.Publish()会 panic:“context not ready”,错误信息里没有明确提示,容易卡在调试里绕半天 - 建议在服务启动阶段统一做健康检查:连上 NATS → 初始化
jetstream.Context→ 尝试js.AccountInfo()确认可用
JetStream 的配置项和客户端行为耦合极深,很多问题表面是“消息丢了”或“重复了”,根子都在流定义、发布方式、订阅策略三者没对齐。最容易被忽略的是:流创建是一次性动作,改配置得删了重建,不是热更新。


















