官方维护的nats.go是唯一推荐的go客户端,因其直接对接nats server协议、低延迟、小内存开销,且支持jetstream和tls 1.3;其他库已归档或功能不全。

为什么选 nats.go 而不是其他 Go NATS 客户端
官方维护的 nats.go 是唯一推荐的 Go 客户端,社区其他库要么已归档,要么不支持 JetStream 或 TLS 1.3。它直接对接 NATS Server 的 wire protocol,没有中间序列化层,延迟低、内存开销小。但要注意:v1.24+ 版本默认启用 ReconnectBufSize,若服务频繁断连且未调大该值,会 silently 丢消息。
- 用
go get github.com/nats-io/nats.go@latest安装,别用gopkg.in/nats-io/nats.go.v1这类旧路径 - 初始化时必须显式设置
MaxReconnects(默认 -1 即无限重连),否则网络抖动时连接可能卡在 reconnect loop 里不报错 - 若用 TLS,
nats.Secure(&tls.Config{...})必须传入完整配置,空&tls.Config{}会导致 handshake failed 错误但日志只显示 “connection closed”
如何正确创建持久化 JetStream 订阅(避免消息堆积后消费停滞)
JetStream 的 durable consumer 不等于“自动续订”,如果 consumer 名字重复或未指定 DeliverPolicy,NATS Server 可能跳过已有消息,导致服务启动后漏消费。关键点是 ConsumerConfig 中三个字段必须协同设置:
-
Durable名必须全局唯一,且不能含下划线(Server 会拒绝创建) -
DeliverPolicy设为nats.DeliverAll或nats.DeliverLastPerSubject,避免默认的DeliverNew导致历史消息不可见 -
AckWait建议设为 30 秒以上,否则处理慢的 handler 会被认为失败并重复投递 - 订阅前先确认 stream 存在:
js.AddStream(&nats.StreamConfig{Name: "orders", Subjects: []string{"order.*"}}),否则js.SubscribeSync会 panic
示例片段:
js, _ := nc.JetStream()
_, err := js.AddStream(&nats.StreamConfig{
Name: "logs",
Subjects: []string{"log.*"},
Retention: nats.LimitsPolicy,
})
if err != nil && !strings.Contains(err.Error(), "stream exists") {
log.Fatal(err)
}
sub, _ := js.SubscribeSync("log.info", nats.Durable("logger-durable"), nats.DeliverAll())
如何防止 context cancel 导致的 unhandled error panic
Go 的 context.WithTimeout 或 context.WithCancel 一旦触发,nats.Conn.Publish 或 sub.NextMsg 会返回 nats.ErrTimeout 或 nats.ErrConnectionClosed。但这些错误若没被 handler 显式检查,就会一路向上 panic——尤其在 HTTP handler 里调用 publish 时容易忽略。
- 永远不要直接
if err != nil { return err },因为nats.ErrTimeout是可重试错误,而nats.ErrConnectionClosed需重建连接 - 对
sub.NextMsg,用select { case 包裹,而不是依赖 ctx 传给 NextMsg - publish 场景下,建议封装一层带重试的 helper:
retryPublish(nc, subject, data, 3, 100*time.Millisecond),避免单次失败就中断业务流
为什么本地开发用 docker run 启动 NATS 要加 -p 和 --name
单纯 docker run -d -p 4222:4222 nats 启动后,Go 服务连不上,常见原因是 DNS 解析失败或端口映射未生效。Docker 默认 bridge 网络下,容器间通信必须用 container name,而 host 模式下又无法复用 localhost。
- 开发时统一用
docker run -d --name nats-server -p 4222:4222 -p 8222:8222 nats,其中 8222 是监控端口,方便 curl http://localhost:8222/streamz 查看 stream 状态 - Go 代码里连接地址写
nats://localhost:4222,不要写nats://nats-server:4222(除非 Go 进程也在容器里) - 如果用
docker-compose.yml,务必为 service 设置network_mode: "host"或显式定义 network 并让 Go 服务加入同一 network,否则 resolver 找不到 nats-server
JetStream 开启需要额外参数:-e "NATS_OPTS=-js" 或挂载配置文件,否则 nc.JetStream() 会返回 “no jetstream server available” 错误。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











