Kratos框架不支持开箱即用的RabbitMQ集成,所有连接、声明、消费逻辑必须手动实现;需选用amqp/v2客户端,显式配置心跳、durable队列/交换机、QueueBind绑定及手动Ack,否则易致消息丢失、静默丢弃或启动panic。

Kratos 框架不支持开箱即用的 RabbitMQ 集成,所有连接、声明、消费逻辑必须手动实现,否则大概率出现消息静默丢失、启动即 panic 或消费者收不到消息。
amqp/v2 客户端选型与连接初始化必须显式配心跳
别用已归档的 streadway/amqp,改用维护中的 github.com/rabbitmq/amqp091-go(即 amqp/v2)。它修复了连接闪断、panic on close 等关键问题。连接时必须设置心跳,否则 RabbitMQ broker 默认 60 秒无响应就主动断连:
amqp.Dial("amqp://guest:guest@localhost:5672/", amqp.WithConnectionHeartbeat(30))- 连接失败不能只靠
err != nil判断,要检查是否是connection refused或 DNS 解析失败 - Kratos 的
app.Run不会阻塞等待 consumer goroutine,必须自己用sync.WaitGroup或app.Register手动维持生命周期
Exchange/Queue 声明与 Bind 必须全部显式调用
Kratos 不提供自动声明或绑定机制,漏掉任意一步都会导致消息路由失败且无报错:
-
channel.ExchangeDeclare("order.exchange", "topic", true, false, false, false, nil)中durable: true必须开启 -
channel.QueueDeclare("order.queue", true, false, false, false, nil)同样要求durable: true,否则 broker 重启后队列消失,后续生产者发消息直接 404 -
即使 exchange 和 queue 名字完全一致,也必须显式调用
channel.QueueBind,否则消息进不了队列,静默丢弃 - Binding key 要和实际 publish 时的 routing key 匹配,topic exchange 下常见误写成
"#"而非"order.*"
消费者必须手动 Ack 且不能依赖 AutoAck
用 channel.Consume 启动消费后,必须立刻起独立 goroutine 处理消息流,并在业务逻辑完成后再调 msg.Ack(false):
- 绝对不要设
autoAck: true,否则 consumer 进程崩溃时未处理完的消息永久丢失 -
msg.Reject(false)可用于重入队,但注意重复投递风险;若需死信,应配合x-dead-letter-exchange声明队列 - 处理逻辑里要包
recover(),避免 panic 导致整个 consumer loop 退出 - 消息体反序列化失败时,建议先
msg.Nack(false, true)重入队一次,再考虑发往 DLX
消息发送端容易忽略的可靠性细节
Kratos 下没有 RabbitTemplate 那类封装,publish 是裸调 channel.Publish,可靠性全靠自己补:
- 必须手动设置
amqp.Publishing{DeliveryMode: amqp.Persistent},否则 broker 重启消息全丢 - 没有内置 confirm 机制,如需发送确认,得自己实现 publisher confirm:监听
conn.NotifyConfirm,并为每条消息维护唯一correlationId - exchange 不存在时
channel.Publish不报错,但消息直接被 broker 丢弃——必须先确保 exchange 已声明成功 - 大消息(>128KB)可能触发 broker 内存限制,建议拆分或启用 compression,但注意 consumer 端也要兼容解压逻辑
最常被跳过的其实是连接池和重连逻辑:Kratos 不管理 amqp.Connection 生命周期,你得自己封装带重试的 dialer,且每次重连后要重新声明 exchange、queue 并重新 bind,否则旧连接上的资源不可复用。这些步骤看似琐碎,但少一个,线上就可能出现“能连上、能发、但没人收”的诡异状态。


















