生产环境应选NATS、Kafka或RabbitMQ;中等规模优先用nats.go配合JetStream,启用durable消费者并显式Ack/Nak;事件结构体须定义带JSON tag的Go struct,并注意时间格式兼容性。

Go 微服务中该用什么消息中间件对接事件?
生产环境别硬写 TCP 或 HTTP 轮询来“模拟事件”。真正可用的只有三类:Kafka、RabbitMQ、NATS。其中 NATS 最轻量,Kafka 吞吐高但运维重,RabbitMQ 语义丰富但 Go 客户端生态略旧。若服务规模中等、追求快速上线,优先选 nats.go;若已有 Kafka 基建或需精确一次(exactly-once)语义,再上 sarama。
如何用 nats.go 订阅并可靠处理事件?
关键不是“连上就收”,而是防止事件丢失和重复处理。必须启用 JetStream,并用 durable 消费组 + ack 显式确认。否则网络抖动时消息直接丢。
nc, _ := nats.Connect("nats://localhost:4222")- 用
js, _ := nc.JetStream()获取 JetStream 接口 - 订阅时指定
durable名称,如js.Subscribe("orders.created", handler, nats.Durable("order-processor")) - 在 handler 中调用
msg.Ack(),而非依赖自动 ack;出错时用msg.Nak()触发重试
漏掉 nats.Durable 或忘了 Ack(),等于裸奔。
事件结构体怎么设计才不容易踩坑?
别用 map[string]interface{} 解析事件体——类型不安全、IDE 无提示、字段改名不报错。必须定义明确的 Go struct,并带 JSON tag。
立即学习“go语言免费学习笔记(深入)”;
type OrderCreatedEvent struct {
ID string `json:"id"`
UserID string `json:"user_id"`
Total float64 `json:"total"`
CreatedAt time.Time `json:"created_at"`
}
还要注意:time.Time 默认序列化为 RFC3339 字符串,但有些生产系统发的是 Unix 时间戳(int64),这时得自定义 UnmarshalJSON 方法,否则解析失败静默丢弃。
本地开发调试时事件总收不到?
常见原因有三个:JetStream 未启用、subject 名字大小写/空格不一致、消费者没起在正确 stream 下。用 nats CLI 快速验证:
- 启动时加
--js:nats-server --js - 查 stream:
nats stream list - 查 consumer:
nats consumer info - 手动发一条测试事件:
nats pub "orders.created" '{"id":"test123","user_id":"u456"}'
如果 nats sub 能收到,但你的 Go 程序收不到,八成是 durable 名冲突或 stream 绑定错了——JetStream 的 consumer 是绑定到 stream 的,不是全局 topic。











