连接 nats 服务器失败时,应将客户端地址从 “nats://localhost:4222” 改为 “nats://host.docker.internal:4222″(docker desktop)或 “nats://172.17.0.1:4222″(docker 默认网关),kubernetes 下则使用 service dns 名如 “nats://nats-cluster:4222″。

连接 NATS 服务器时,connect() 超时或报 no servers available 怎么办
本地开发最常卡在这一步:明明 docker run -p 4222:4222 nats:latest 跑起来了,但 Node.js 或 Python 客户端死活连不上。根本原因不是服务没启,而是客户端默认只连 "nats://localhost:4222",而 Docker Desktop(尤其 macos/windows)里 localhost 指向宿主机,容器内网络却走的是桥接网关,localhost 在容器内部不等于宿主机。
- Node.js 开发时,把地址换成
"nats://host.docker.internal:4222"(Docker Desktop 支持),或直接用"nats://172.17.0.1:4222"(Docker 默认网桥网关 IP) - Python 使用
nats-py时,同样要改地址;如果用asyncio启动多个协程共用一个连接,记得用await nc.flush()主动刷缓冲,否则首次 publish 可能静默失败 - Kubernetes 环境下,别硬写
localhost,应通过 Service DNS 名访问,比如"nats://nats-cluster:4222",且确保NatsClusterCR 已就绪(kubectl get natsclusters看 STATUS 是Running)
发布消息后订阅者收不到,subscribe() 为什么像“没生效”
这不是 bug,是 NATS 的主题匹配机制在起作用:它严格区分大小写、空格和点号层级,"orders.created" 和 "orders.created "(尾部空格)完全不匹配,也不会报错,只是静默丢弃。
- 所有主题名统一用小写 + 英文点分隔,例如
"user.Event.created",避免用下划线或大写字母 - Node.js 中
nc.subscribe("orders.created", handler)必须在nc.publish("orders.created", ...)之前调用;如果先 publish 再 subscribe,那条消息就永远丢失了(基础 NATS 不缓存未订阅主题的消息) - Python 的
nats-py默认使用异步回调,若 handler 函数里有阻塞操作(比如同步 http 请求),会卡住整个连接的事件循环——必须用await asyncio.to_thread(...)或改用线程池
需要消息不丢?别只开 JetStream,先确认这三件事
JetStream 不是开关一按就“自动持久化”,它是一套需显式配置的流式存储系统。启用后若仍丢消息,大概率栽在这几个环节上。
- 创建流(Stream)时,必须指定
subjects匹配你实际 publish 的主题,比如流配置subjects: ["orders.*"],你就不能往"payments.completed"发——它压根不进流 - 消费者(Consumer)要设
deliver_policy: "all"才能从头重放;默认是"last_received",重启后只收新消息 - .NET 项目用
NATS.Client时,Request()方法底层仍是 publish + reply subject,它本身不走 JetStream;想持久化请求响应链,得手动把请求发到带 JetStream 的主题,并由服务端用msg.Reply发回——这个 reply 主题也得单独建流
queue group 用于负载均衡,但为什么两个实例还在抢同一消息
Queue Group 是 NATS 实现服务水平扩展的关键,但它只在“同组内”做竞争消费。如果看到两个实例都处理了同一条消息,基本是名字没对齐或连接隔离了。
- 所有实例订阅时必须用**完全相同的**
queue名,比如nc.subscribe("logs", queue="log-processor", cb=...),拼错一个字母(如"log-processor ")就变成独立组 - Go 客户端默认开启
reconnect,但 Node.js 的nats.js需手动传reconnect: true, max_reconnect_attempts: -1,否则断连后旧 queue group 成员不会自动退出,新实例加入时可能短暂出现重复消费 - 测试时别用同一个进程起多个 subscriber —— 它们共享连接上下文,NATS 会当成一个消费者;必须用不同进程或容器模拟真实实例
JetStream 的流配置、queue group 的命名一致性、客户端重连策略——这些地方不细看文档就动手,十次部署九次要返工。尤其是主题命名和流绑定,一旦上线再改,就得停服重建流,数据还可能丢。