[TOC] #### 1. 前言 --- 用户投诉:我下单了,为什么没收到短信通知 ? 你开始排查 + 查数据库:订单创建成功,状态正常 + 查 RabbitMQ 管理界面:队列里没有消息,Ready 是 0 + 查消费者日志:没有报错,运行正常 那问题来了:消息到底去哪了 ? 排查为什么这么难 ? 一条消息从 Producer 到 Consumer,中间经过的环节很多: ```plaintext Producer → Exchange → Queue → Consumer ``` 每个环节都可能出问题: + Producer 发了吗?发到哪个 Exchange 了? + Exchange 收到了吗?路由到哪个 Queue 了? + Queue 收到了吗?消息还在里面吗? + Consumer 取了吗?处理了吗?ACK 了吗? 如果没有任何记录,只能靠猜,我们需要的是一个「消息轨迹」,能看到消息经过了哪些环节 #### 2. 追踪工具 --- RabbitMQ 提供了 Firehose、Tracing 插件等追踪能力,可以记录消息的完整路由过程 但实际开发中,大部分问题不需要用到这些高级工具,大部分问题首先依靠这三样东西就能定位 + Producer 日志:消息发出去了吗?有没有报错 ? + RabbitMQ 管理后台:队列里有没有消息?Exchange 有没有绑定 ? + Consumer 日志:消费者在运行吗?有没有收到消息?有没有报错 ? 只有比较复杂的问题,比如消息路由过程不明确、配置正确但行为异常,才需要开启 Tracing 插件来追踪消息的完整轨迹 #### 3. 线上问题排查思路 --- 回到开头的问题:用户下单了,没收到短信 排查 RabbitMQ 问题时,不要跳着查,按照消息流转方向逐层排查,效率最高 排查步骤: 第一步:查 Producer 消息发出去了吗 ?可以在 Producer 代码里加日志: ```php try { $channel->basic_publish($message, 'sms_exchange', 'sms'); echo "消息发送成功\n"; } catch (\Exception $e) { echo "消息发送失败:{$e->getMessage()}\n"; } ``` 如果开了 Publisher Confirm,确认收到了吗 ? 第二步:查 Exchange 消息到达 Exchange 了吗 ? 打开管理界面,看 Exchange 页面有没有这个 Exchange,看 Message rates 有没有消息流入 第三步:查 Queue 消息在 Queue 里吗 ? 看 Queues 页面,Ready 和 Unacked 是多少,如果 Ready 是 0,消息可能已经被消费了,或者根本没进来 第四步:查 Consumer 消费者在运行吗 ? 看 Connections 和 Channels 页面,消费者有没有连接,查消费者日志,有没有报错 第五步:查消息追踪 如果以上都看不出问题,可以开启 Tracing 插件,看消息的完整路由过程,但大多数时候,前四步就能找到问题 最常见的几个坑: | 现象 | 可能原因 | | ------------ | ------------ | | 消息发了,Queue 里没有 | Exchange 类型或 routing key 不匹配 | | Queue 里有消息,Consumer 没收到 | Consumer 连接的队列名写错了 | | Consumer 收到了,但没处理 | 回调函数有 bug,没打印日志 | | 处理了但 Queue 里还有 | 没有发 ACK,消息一直 Unacked | | 消息突然没了 | 没有持久化,RabbitMQ 重启了 | 大部分线上问题,靠管理界面 + 日志就能定位,Tracing 插件是进阶工具,问题复杂的时候再用 #### 4. 本文小结 --- 排查思路:Producer → Exchange → Queue → Consumer,按照消息流转方向逐层排查 工具: + 日志:Producer 日志和 Consumer 日志是第一线索 + 管理界面:看队列状态、连接数、消息速率 + Tracing 插件:复杂问题的进阶工具 线上绝大多数 RabbitMQ 问题,最终都能在「日志 + 管理后台」这两处找到线索 不要一遇到问题就先怀疑 RabbitMQ 本身,先检查自己的代码和配置 下一讲,我们来聊一个更大的话题:RabbitMQ 挂了怎么办 ?