NATS 生产环境必须配置重连、凭证和 JetStream 持久化,连接需延迟至配置加载后由 app 生命周期管理,消费端须用 QueueSubscribe 并设 MaxInflight,主题名严格匹配,JetStream 流需指定保留策略且消息需带 MsgID。

直接上生产环境跑裸连 nats.Connect(nats.DefaultURL),不出三天就会因为网络抖动、服务重启或配置未加载而 panic——不是 NATS 不稳定,是你没让它活过第一个重连周期。
别在 main() 里初始化 NATS 客户端
Kratos 或其他依赖配置驱动的框架中,conf.Nats.URL 在 config.ToType(&conf.Nats) 执行前是空字符串,此时调 nats.Connect("") 会解析成 nats://,触发 nats: no servers specified 错误并 panic。
- 必须等框架配置加载完成后再建连接:放进
app.New()回调里,或注册为 DI 依赖项,在需要时注入 - 千万别在
init()或main()开头就执行nats.Connect() - 连接对象
*nats.Conn要由 app 生命周期管理,不能自己defer nc.Close()—— 那等于一连就关
生产环境连接必须配重连与凭证策略
本地用 nats-server 单节点没问题,但生产环境裸连等于裸奔:默认不重试、无超时、无健康检查,一次 TCP 断连就卡死。
- 显式加重连参数:
nats.MaxReconnects(60)、nats.ReconnectWait(2*time.Second)、nats.ReconnectJitter(100*time.Millisecond, time.Second) - 密码类认证别拼 URL:
nats.UserCredentials("nats.creds")加载凭证文件,而非写死nats://user:pass@host:port - 若启用 JetStream,连接后立刻调
jetstream.New(nc),否则首次js.Publish()可能 panic
高吞吐消费必须用 QueueSubscribe() + MaxInflight
用 Subscribe() 处理事件流,所有消息串行进同一个 goroutine,QPS 上不去,CPU 利用率低,延迟飙升——这不是业务逻辑慢,是单点瓶颈。
立即学习“go语言免费学习笔记(深入)”;
- 微服务多实例部署时,统一用
QueueSubscribe("orders.created", handler, nats.Queue("order-processor"))实现负载分摊 - 必须设
nats.MaxInflight(256)(按业务吞吐调),否则默认 inflight=1,又回到串行 - 主题名严格字符串匹配:
"order.created"和"order.created.v1"完全无关,发布/订阅两端 subject 必须完全一致
JetStream 不开 = 消息不持久,不是你代码丢了
NATS 默认纯内存转发,消费者掉线期间发的消息直接蒸发。这不是 bug,是设计——想“不丢”,必须开 JetStream 并配对流和消费者语义。
- 连接后立即创建上下文:
js, _ := jetstream.New(nc),再创建流:js.CreateStream(...) - 流必须指定
RetentionPolicy:jetstream.InterestPolicy(按兴趣保留)或jetstream.WorkQueuePolicy(工作队列模式),否则即使开了 JS,消息也不存 - 消费端用
js.Subscribe("orders.created", handler, nats.DeliverPolicy(nats.DeliverAll))才能从头消费;DeliverLastPerSubject会跳过中间事件 - 去重要生效,发消息必须带
nats.WithMsgID("order-123"),且流配置的Duplicates: 2*time.Minute是窗口期,不是保留时间
最常被忽略的是:JetStream 的流配置、消费者 ACK 策略、以及 msg.Ack() 调用时机——三者缺一,消息就可能重复或丢失,跟代码逻辑是否正确无关。


















