[TOC] #### 前言 --- 这是我们 RabbitMQ 40 讲的最后一讲,前面 39 讲我们从零开始,学了概念、装了环境、写了代码、做了实战 这一讲我们换个角度:线上遇到问题怎么办 ? 本文整理了一份常见问题清单,遇到问题的时候可以直接查 #### 问题一:消息发不出去 --- 现象:Producer 代码没报错,但 Queue 里没有消息 排查步骤: + Exchange 存在吗?去管理界面看 Exchanges 页面 + routing key 对吗?Producer 发的和 Queue 绑定的是不是一致 + Exchange 类型对吗?Direct 要精确匹配,Topic 要通配符匹配 + 开了 Publisher Confirm 吗?看看有没有收到 nack 最常见的原因:routing key 写错了,或者 Exchange 类型不匹配 #### 问题二:消息发出去了,但 Queue 里没有 --- 现象:Producer 日志显示发送成功,但 Queue 的 Ready 是 0 排查步骤: + 消息是不是被消费者消费了 ?看 Unacked 是不是有数字 + 队列绑定对了吗?去管理界面看 Queue 的 Bindings + 是不是发到了错误的 Exchange ?检查 Producer 代码 最常见的原因:消息已经被消费了,但消费者处理有问题,你以为消息没到 #### 问题三:消费者收不到消息 --- 现象:Queue 里有消息,但消费者不处理 排查步骤: + 消费者连上了吗?看管理界面的 Connections 页面 + 消费者订阅的队列名对吗?代码里写的和声明的是不是一致 + 消费者是不是卡住了?看 Unacked 数字是不是一直在涨 + prefetch 设置是不是太小了?消费者一次只取 1 条,处理太慢 最常见的原因:消费者代码里队列名写错了,或者回调函数有 bug #### 问题四:消息重复消费 --- 现象:同一条消息被处理了多次 排查步骤: + 有没有开手动 ACK ?默认自动 ACK 可能导致重复 + 消费者处理时间是不是太长 ?RabbitMQ 可能认为超时了重新投递 + 有没有做幂等处理 ?消费者重启后消息会被重新投递 解决方案:开手动 ACK + 业务层做幂等(第 27 讲讲过) #### 问题五:消息丢失 --- 现象:消息发出去了,但后来找不到了 排查步骤: + 队列持久化了吗 ?`durable = true` + 消息持久化了吗 ?`delivery_mode = PERSISTENT` + RabbitMQ 重启过吗 ?非持久化的消息重启就没了 + 消费者开了手动 ACK 吗 ?自动 ACK 消费者挂了消息就丢了 解决方案:队列持久化 + 消息持久化 + 手动 ACK(第 14 讲讲过) #### 问题六:队列消息堆积 --- 现象:Ready 数字一直在涨,消费者处理不过来 排查步骤: + 消费者在运行吗 ?看 Connections 页面 + 消费者处理速度够吗 ?看 deliver rate 和 publish rate 的差距 + 消费者是不是卡在某个操作上 ?比如外部接口超时 解决方案:增加消费者数量、优化处理逻辑、控制 prefetch(第 39 讲讲过) #### 问题七:内存暴涨 --- 现象:RabbitMQ 内存占用越来越高 排查步骤: + 是不是有大量消息堆积 ?消息存在内存里会占空间 + 是不是连接数太多 ?每个连接都占内存 + 是不是有消费者连着但不消费 ?Unacked 数字很高 解决方案:设置队列最大长度(x-max-length),超出的消息自动丢到死信队列或丢弃 #### 问题八:连接数爆满 --- 现象:新客户端连不上 RabbitMQ 排查步骤: + 是不是每次发消息都新建连接 ?应该复用连接 + 是不是消费者断开后没有正确关闭连接 ? + 系统的文件描述符限制是不是太低了 ? 解决方案:使用连接池,正确关闭连接,调高系统限制 #### 问题九:网络分区(脑裂) --- 现象:集群中部分节点互相连不上 排查步骤: + 检查节点之间的网络是否通畅 + 看管理界面有没有 `partitions` 警告 + 用 `rabbitmqctl cluster_status` 查看集群状态 解决方案:修复网络,重启节点,或者使用 Quorum Queue 减少脑裂影响(第 32 讲讲过) #### 问题十:RabbitMQ 启动失败 --- 现象:容器启动后立刻退出 排查步骤: + `docker logs rabbitmq` 看日志 + 是不是端口被占了? + 是不是 Erlang Cookie 不一致?集群环境下常见 + 是不是磁盘空间不足?RabbitMQ 磁盘不足会拒绝写入 解决方案:根据日志具体分析,最常见的就是端口冲突和磁盘空间不足 #### 排错通用流程 --- 不管遇到什么问题,按这个顺序排查: ```plaintext 1. 看日志(Producer 日志 + Consumer 日志 + RabbitMQ 日志) ↓ 2. 看管理界面(队列状态、连接数、消息速率) ↓ 3. 看代码(routing key、队列名、Exchange 类型) ↓ 4. 看配置(持久化、ACK、prefetch) ↓ 5. 看服务器(内存、磁盘、网络) ``` 大部分问题在前 3 步就能找到原因 #### 本文小结 --- 这份清单覆盖了 RabbitMQ 最常见的 10 个问题 遇到问题不要慌,按照消息流转方向逐层排查:Producer → Exchange → Queue → Consumer 先看日志,再看管理界面,最后看代码和配置 线上绝大多数问题,都能在「日志 + 管理后台」这两处找到线索 #### 学 RabbitMQ 最容易踩的坑 --- 很多同学刚开始学 RabbitMQ 的时候,最关注的是:Exchange 怎么配置、Queue 怎么声明、消息怎么发送 但真正到了项目里,踩坑最多的反而是: + ACK 没处理好 + 消息重复消费 + 队列堆积 + 路由规则配置错误 + 集群故障 RabbitMQ 真正难的地方,从来不是 API,而是理解消息在系统里的流转过程 只要把 Producer → Exchange → Queue → Consumer 这条链路想清楚,大部分问题都能定位出来 #### RabbitMQ 消息队列 40 讲完结 --- 到这里,RabbitMQ 40 讲就全部讲完了 回顾一下我们学了什么: + 第 1-5 讲:为什么需要消息队列 + 第 6-10 讲:RabbitMQ 环境搭建和核心概念 + 第 11-15 讲:Producer、Consumer、Queue、消息 + 第 16-20 讲:Exchange 四种类型 + 第 21-25 讲:TTL、死信队列、延迟队列、消息可靠性 + 第 26-28 讲:幂等性、消息追踪 + 第 29-33 讲:集群与高可用 + 第 34-38 讲:实战项目 + 第 39-40 讲:性能优化与排错 从零到实战,从单机到集群,这套教程覆盖了 RabbitMQ 的核心知识 不要追求记住每一个配置项,真正重要的是: + 知道 RabbitMQ 能解决什么问题 + 知道什么时候该用 + 知道出了问题从哪里查 这些能力,比背命令更有价值,剩下的就是在实际项目中多用、多踩坑、多总结 学完只是开始,用起来才是真本事 如果这是你第一次系统学习 RabbitMQ,那么恭喜你 到这里,你已经完成了从「知道 RabbitMQ 是什么」到「能够在项目里落地 RabbitMQ」的跨越 后面真正需要积累的,是项目经验 多做几个异步任务,多做几个延迟队列,多观察几次消息堆积,很多知识会比看十遍教程理解得更深