Iris 不能直接接入 RabbitMQ,因其本身不提供消息队列能力,需手动集成 streadway/amqp 等客户端并自行管理连接、Channel 生命周期、错误重连与消费逻辑。

为什么 Iris 不能直接“接入” RabbitMQ
Iris 是一个 Go 语言的 Web 框架,它本身不提供消息队列能力,也不封装 RabbitMQ 客户端。所谓“接入”,本质是你在 Iris 应用中手动集成官方或社区推荐的 AMQP 客户端库(如 streadway/amqp),并自行管理连接、通道、发布/消费逻辑。Iris 只负责 HTTP 请求生命周期,RabbitMQ 的连接复用、错误重连、并发消费等都得你写清楚。
用 streadway/amqp 连接 RabbitMQ 的关键配置点
Go 生态最常用的是 streadway/amqp,它轻量、稳定、符合 AMQP 0.9.1 协议。但容易出错的地方集中在连接和 channel 生命周期上:
-
amqp.Dial()返回的*amqp.Connection必须全局复用(例如通过sync.Once或依赖注入),不能每次发消息都新建——否则会快速耗尽 TCP 连接或触发 RabbitMQ 的连接限制 - 每个业务操作(如一次 HTTP handler 执行)应创建独立的
amqp.Channel,用defer ch.Close()确保释放;Channel不是线程安全的,绝不能跨 goroutine 复用 - 连接字符串格式必须正确:
amqp://user:pass@host:port/vhost,其中vhost默认是/,但 URL 编码后要写成%2F,否则连接失败且报错模糊(常见错误:Exception (530) Reason: "NOT_ALLOWED - vhost not found") - 建议启用连接心跳:
amqp.Config{Heartbeat: 10 * time.Second},避免 NAT 超时断连后无感知
在 Iris 中安全地发送消息(Publisher)
Iris 的 iris.Context 是请求作用域,不能持有长期连接。所以消息发送逻辑必须从全局连接池取 Channel,发完立刻关闭:
func publishOrderCreated(ctx iris.Context) {
ch, err := globalConn.Channel()
if err != nil {
ctx.StatusCode(500)
ctx.WriteString("channel create failed")
return
}
defer ch.Close()
<pre class="brush:php;toolbar:false;">err = ch.ExchangeDeclare(
"order.exchange", "topic", true, false, false, false, nil,
)
if err != nil {
ctx.StatusCode(500)
ctx.WriteString("exchange declare failed")
return
}
body := []byte(`{"order_id":"123","user_id":456}`)
err = ch.Publish(
"order.exchange",
"order.created",
false,
false,
amqp.Publishing{
ContentType: "application/json",
DeliveryMode: amqp.Persistent, // 持久化消息
Body: body,
},
)
if err != nil {
ctx.StatusCode(500)
ctx.WriteString("publish failed")
return
}
ctx.WriteString("ok")
}
注意:DeliveryMode: amqp.Persistent 和 ExchangeDeclare(..., durable: true) 必须同时设置,否则重启 RabbitMQ 后消息或交换机丢失。
用 goroutine 启动消费者(Consumer),别塞进 Iris handler
Iris 的 HTTP server 不适合长期运行消费循环。你应该在 main() 启动后单独起 goroutine 运行消费者,并手动处理 ACK/NACK:
- 使用
ch.Consume()拉取消息,不要用阻塞式ch.NotifyConsume()回调 - 务必调用
ch.Qos(1, 0, false)控制预取数量,否则高并发下内存暴涨、消息堆积 - 处理失败时,用
delivery.Nack(false, false)(不重入队)或发往死信队列,避免无限重试卡死 - 反序列化、DB 写入等 IO 操作必须加超时控制,防止 goroutine 泄漏
复杂点在于:消费者需要与 Iris 共享日志、配置、数据库连接等资源,建议用结构体封装 consumer 实例,并在初始化时传入所需依赖。最容易被忽略的是——消费者崩溃后没有自动拉起机制,上线前务必补上 recover() + 重连逻辑。











