iris框架mvc默认不支持rabbitmq,因其仅管理http生命周期,不内置消息队列能力;rabbitmq需在service层手动初始化连接、复用channel、处理错误及关闭逻辑。

为什么 Iris 的 MVC 默认不支持 RabbitMQ
Iris 是一个 Go 语言 Web 框架,它的 MVC 结构(Controller、Service、Repository)本身不内置任何消息队列能力。它只负责 HTTP 请求生命周期管理,而 RabbitMQ 是外部中间件,需要你显式建立连接、声明队列、收发消息。框架不会帮你自动绑定 amqp.Connection 或封装 channel.Publish —— 这些都得你自己在 Service 层或独立模块里做。
在 Service 层初始化 RabbitMQ 连接并复用
别在每次 HTTP 请求里新建 amqp.Connection,那会快速耗尽 socket 资源,也违背 RabbitMQ 最佳实践。正确做法是:应用启动时建立一次连接,并在 Service 中注入该连接或封装好的 channel 实例。
- 使用
sync.Once或依赖注入容器(如github.com/uber-go/dig)确保单例 - 连接字符串格式必须是
amqp://user:pass@host:port/vhost,注意 vhost 默认是/,但 URL 编码后要写成%2F - 务必设置
amqp.Config{Dial: dialTimeout}避免阻塞启动,超时建议设为 5s - 连接断开后,不要静默重试;应监听
notifyClose并触发重建逻辑(否则后续channel.Publish会 panic)
Controller 调用 Service 发送消息时的常见错误
很多开发者在 Controller 里直接调用 service.PublishOrderEvent(order),却没处理底层失败。结果就是:HTTP 返回成功了,消息其实根本没进 RabbitMQ。
-
channel.Publish返回error时,不能只打日志就完事;需决定是重试(最多 2 次)、降级(写本地 DB 待补偿),还是直接返回 500 - 不要把消息体(
body)直接传结构体指针;必须序列化为[]byte,推荐json.Marshal,避免encoding/gob兼容性问题 - 如果用了
exchange(比如topic类型),routing_key必须匹配规则,否则消息会被丢弃且无提示 —— 建议先用fanout测试通路 - 忘记设置
amqp.Publishing{DeliveryMode: amqp.Persistent},RabbitMQ 重启后消息就丢了
消费者怎么和 Iris 应用共存而不冲突
很多人想让 Iris 启动时顺带跑一个消费者 goroutine,结果发现 HTTP Server 启动后程序就卡住、无法响应请求。这是因为消费者用的是阻塞式 channel.Consume,而没把它放到独立 goroutine 里。
- 必须用
go func() { ... }()启动消费者循环,且内部要处理msgs, err := channel.Consume(...)的错误分支 - 消费者回调函数里别直接操作 Iris 的
app或Router,它们不是线程安全的;所有业务逻辑应下沉到 Service 层 - 若消费者要调用数据库,别复用 HTTP 请求里的
*sql.DB实例 —— 它们生命周期不同,容易出现连接泄漏 - 关闭时需显式调用
connection.Close()和channel.Close(),否则进程退出后 RabbitMQ 会保留 unack 状态数小时
amqp 包,在合适的位置(Service 初始化、Controller 调用点、独立 goroutine)把连接、发布、消费三件事串起来。最容易被忽略的,是连接生命周期管理和消费者 panic 后的恢复机制 —— 这两处一出问题,消息就静默丢失或堆积。











