本地开发用nats-server单节点,默认连0.0.0.0:4222;生产需配重连策略、凭证文件、jetstream上下文;消息不丢需启用jetstream并正确配置流与订阅;去重需设msgid和duplicates窗口;subject通配符*匹配单段、>匹配多级末尾。

怎么连上NATS服务器,别一上来就panic
本地开发直接跑 nats-server 单节点就行,别急着搭集群。默认监听 0.0.0.0:4222,Go 客户端用 nats.Connect(nats.DefaultURL) 能连上——但这只是“裸连”,没重试、没超时、没健康检查,网络抖动一次就断连卡死。
- 生产环境必须显式加重连策略:
nats.MaxReconnects(60)、nats.ReconnectWait(2*time.Second)、nats.ReconnectJitter(100*time.Millisecond, time.Second) - 别把
nats://user:pass@host:port这种带密码的 URL 写死在代码里,改用nats.UserCredentials("user.creds")加载凭证文件 - 如果服务启用了 JetStream,连接后要立刻调用
jetstream.NewContext(nc)创建上下文,不能等发消息时才初始化,否则第一次js.Publish()可能 panic
发布-订阅消息为什么总丢?不是bug是设计
NATS 默认纯内存转发,消费者掉线期间发布的消息直接丢弃。这不是 bug,是设计取舍。想“不丢”,必须启用 JetStream 并配好流(Stream)。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 创建流时必须指定
Subjects和RetentionPolicy,比如jetstream.InterestPolicy(按兴趣保留)或jetstream.WorkQueuePolicy(工作队列模式),否则即使开了 JetStream,消息也不会持久化 - 订阅时要用
js.Subscribe("orders.created", handler, nats.DeliverPolicy(nats.DeliverAll))才能从头消费;若用DeliverLastPerSubject,重启后可能跳过中间事件 - NATS 不保证 exactly-once,只保证 at-least-once,消费者必须自己做幂等:比如用
order_id去重 + 数据库唯一索引拦截
JetStream 发布消息重复/乱序,问题不在服务端
重复和乱序不是 NATS 服务端的问题,而是客户端没按规范用。JetStream 本身支持去重,但得手动开,且窗口期得设对。
- 发消息必须加
nats.WithMsgID("order-123"),否则Duplicates配置无效;ID 要业务唯一,不能用uuid.New()这类无意义随机值 - 流配置里的
Duplicates: 2*time.Minute是去重窗口,不是“保留时间”。如果业务处理耗时超过这个值,重复消息仍可能被接受,得同步调大该值或优化处理逻辑 - 别在循环里并发调用
js.Publish()而不控制顺序:NATS 不保证多 goroutine 发布的时序,同一subject下消息可能乱序。需顺序关键场景,应串行发布或用单个 goroutine +channel缓冲
subject 通配符怎么写才不踩坑
NATS 的 subject 是用 . 分层管理的,底层靠 tree module 匹配,两个通配符 * 和 > 行为差异很大,写错就收不到消息。
-
*匹配单段,比如aa.*.cc能匹配aa.11.cc、aa.zngw.cc,但不能匹配aa.11.zngw.cc -
>必须放在末尾,匹配后面所有层级,比如aa.>匹配aa.b、aa.b.c、aa.x.y.z - 队列订阅用
nc.QueueSubscribe("orders.created", "worker-group", handler),同一队列组内只有 1 个消费者收到消息,适合负载分发;普通Subscribe是广播,所有订阅者都收
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










