第15章:RabbitMQ 日常运维、日志与初级故障排查
发布时间:2026/9/10 19:08:32 锦皓数字建站

1. 项目背景基础篇到了收口拓扑会配、Confirm 会写、权限会拆但周五晚上仍然只有一句话工单——「MQ 不行了」。现场常见五种脸应用连不上端口、DNS、TLS、口令、VHost。连上了 403权限、正则、标签误会。406参数冲突、废弃临时队列、confirm 与 tx 互斥。队列里有货没人拿消费者挂、prefetch 堵死、autoAck 丢了以为没发。发布全部超时告警、磁盘、FD 耗尽、blocked。没有标准排查顺序每个人重启的对象不同有人重启应用有人重启 Broker有人down -v。测试也无法回归「昨天那种不行」因为步骤随心情。本章把运维命令、日志落点和五类故障做成可抄的清单。不引入 Prometheus第 27 章不引入集群脑裂第 17 章。目标是测试能按清单在实验室复现开发能按清单看回复码运维能按清单决定动哪一层。日志是排障的第三只眼。第 3 章把日志打到 console 供采集。级别乱开 debug 会自己打满磁盘触发第 14 章告警。排障时临时提高级别结束必须改回。先ping / listeners / alarms 再用户、VHost、list_queues、consumers 然后应用日志里的 reply-code 最后才考虑重启 Broker把「最后」放在最后是本章最大的态度。2. 项目设计小胖把医院分诊台的牌子拍下来红黄绿。小胖这不就是分诊吗发烧去内科。为啥 MQ 还要一堆英文命令直接重启最痛快食堂后厨着火不也是先拉电闸大师后厨拉电闸大厅正在上的菜全毁。Broker 重启会让未 Confirm 的发布、未 Ack 的消费一起进入重试风暴。分诊是先量体温ping、看门口堵不堵listeners、看水库alarms再决定要不要停灶。测试要把五种病做成五个病例包而不是一个「环境重置」按钮。技术映射ping进程活listeners端口在听alarms拒写reply-code这次操作的诊断。小白is_running和is_serving有何不同日志在容器 stdout 还是文件NOT_FOUND 是通道还是连接级FD 耗尽怎么看如何安全地复现磁盘告警而不炸实验室测试账号做故障注入会不会把权限玩坏sysmon 是什么大师running 是应用起来serving 是开始接客启动窗口两者不同第 2 章 boot step。我们的镜像日志在 stdout用docker logs若打开 file 要找数据目录。NOT_FOUND 多为通道异常对象不存在连错 VHost 也可能在开连接时失败。FD 看rabbitmq-diagnostics status与系统ls /proc/pid/fd。磁盘告警用第 14 章思维优先讲 SOP真写满只用独立 volume 的实验机。故障注入用 lab 用户和 lab 队列做完 provision 脚本可重入。rabbit_sysmon_handler接 Erlang 系统监控事件CPU 飙高时日志里可能有 busy 进程第 30 章再深挖。小胖五种病例我只要口诀连不上查门403 查户口406 查声明没消费查人超时查红灯。大师很好。补一条同一口诀里禁止第一步down -v。数据目录不是草稿纸。测试用例标题必须含故障类型禁止只叫test_mq。技术映射每种故障对应固定命令序列序列本身就是回归用例。小白健康检查 aliveness-test 为什么不进 SOP 第一条日志级别怎么临时改Channel 异常后连接还在应用为啥整池不可用大师aliveness 会真实收发高频探针有副作用第 5 章。SOP 第一条用diagnostics ping与health/checks/local-alarms。临时改级别用rabbitmqctl set_log_level debug结束改回 info。通道异常若应用把整条 Connection 关掉第 4 章池子会雪崩——排障时看客户端是否「一 406 就 close connection」。小胖实验按五病例走一遍产出检查单给测试当 JSON 或表格。第 16 章综合实战会用这张表做验收。3. 项目实战3.1 环境准备节点健康基线先采一份dockerexecrabbit-promo-1 rabbitmq-diagnosticspingdockerexecrabbit-promo-1 rabbitmq-diagnostics listenersdockerexecrabbit-promo-1 rabbitmq-diagnostics alarmsdockerexecrabbit-promo-1 rabbitmq-diagnostics statusdockerexecrabbit-promo-1 rabbitmq-diagnostics memory_breakdowndockerlogs rabbit-promo-1--tail50运行结果ping 成功listeners 含 5672/15672alarms 空。把输出存ch15-baseline.txt。日志相关启动在 prelaunch。排障时dockerexecrabbit-promo-1 rabbitmqctl set_log_level info3.2 病例 A连不上端口 / 口令 / VHost步骤目标区分 TCP 拒绝、鉴权失败、VHost 不存在。# promo-mq/ch15/fault_connect.pyimportpikafrompika.exceptionsimportAMQPConnectionError,ProbableAccessDeniedErrordeftry_conn(port,user,pwd,vh):try:pika.BlockingConnection(pika.ConnectionParameters(127.0.0.1,port,vh,pika.PlainCredentials(user,pwd),socket_timeout3,connection_attempts1))print(OK,port,user,vh)exceptExceptionase:print(type(e).__name__,port,user,vh,str(e)[:100])try_conn(5673,app_order,ord_dev_2026,order)# 错端口try_conn(5672,app_order,wrong,order)# 错口令try_conn(5672,app_order,ord_dev_2026,no-such)# 错 VHosttry_conn(5672,app_order,ord_dev_2026,order)# 对照成功SOP-ATest-NetConnection/nc测端口 → 对 listeners → 对用户表 → 对 VHost 列表。不要先改代码重试间隔。坑错口令有时延迟关闭防扫号不要当「网络慢」。坑成功对照必须放在最后证明实验室本身好。3.3 病例 B403 权限复用第 11 章acl_lab.py跨 VHost。SOP-Blist_user_permissions→ 是否在该 VHost 有行 → 正则是否锚点错误 →重连再测。日志关键字access_refused。3.4 病例 C406 参数冲突# promo-mq/ch15/fault_406.pyimportpikafrompika.exceptionsimportChannelClosedByBroker cpika.BlockingConnection(pika.ConnectionParameters(127.0.0.1,5672,order,pika.PlainCredentials(app_order,ord_dev_2026)))chc.channel()ch.queue_declare(q.order.pay,durableTrue)try:ch.queue_declare(q.order.pay,durableTrue,arguments{x-max-length:3})exceptChannelClosedByBrokerase:print(406 expected,e.reply_code,e.reply_text[:200])print(conn still open,c.is_open)c.close()运行结果406 PRECONDITION_FAILED inequivalent连接仍开第 4 章。SOP-C读 reply_text →list_queues看已有 arguments/policy → 不要 406 就关连接池。废弃临时队列同样走 406对照第 7 章。3.5 病例 D有消息无消费步骤目标停掉消费者ready0consumers0。dockerexecrabbit-promo-1 rabbitmqctl list_queues-porder name messages consumersdockerexecrabbit-promo-1 rabbitmqctl list_consumers-porderSOP-Dconsumers0 先拉应用不 Purge。unacked≈prefetch 且 ready 仍涨 → 忘 Ack 或处理卡住第 9 章。深度0 但业务说没收到 → 查 autoAck 丢失或发错 VHost。人为挂死启动只 sleep 不 Ack 的消费者观察 unacked。测试用例名称given_stuck_consumer_then_unacked_equals_prefetch。3.6 病例 E发布超时 / 红灯对照第 14 章 SOP不重复拧水位。检查dockerexecrabbit-promo-1 rabbitmq-diagnostics alarmsdockerexecrabbit-promo-1 rabbitmqctl list_connections name user statestateblocked即红灯。FD 耗尽时 status 里文件描述符接近上限listeners 仍在但新连接失败表现像病例 A要用 status 区分。SOP-Ealarms → blocked 连接 → 消费者 → 磁盘 df → 才考虑扩容或重启。3.7 日志与回复码速查码含义常见原因级别311content-too-large消息过大通道320connection-forced管理踢人连接403access-refused权限通道或连接404not-found无交换机/队列通道406precondition-failed参数冲突、非法组合通道530not-allowedVHost 等连接541internal-error服务端异常连接SOP-日志复现时set_log_level debug不超过 10 分钟同时docker logs -f按 connection_name 过滤第 4 章 client_properties。结束改回 info。禁止把 debug 写进 Git conf 当默认。3.8 测试检查单可交给第 16 章编号故障前置操作期望清理TC-CH15-A1错端口基线绿连 5673连接失败无TC-CH15-A2错口令基线绿错误密码鉴权失败无TC-CH15-B1跨 VHostch11 账号连 marketing拒绝无TC-CH15-C1406已有 durable 队列不同 arguments 再 declare406 且连接仍开无TC-CH15-D1无消费者灌 5 条停应用consumers0消息仍在拉起应用TC-CH15-E1告警实验室水位见第 14 章blocked恢复水位完整清单路径column/samples/ch15/checklist.md。五病例的公共夹具每个用例开始读 alarms 必须为空否则跳过并失败标明「环境脏了」。每个用例结束不得留下 debug 级别、不得留下 0.01 水位、不得留下错的 Policy。用 try/finally 比靠自觉强。CI 里顺序建议 A→B→C→DE 因会改水位放最后且独占 runner。标题用 given/when/then方便失败时值班对照 SOP 章节。不要把五种故障塞进一个测试函数失败时不知道走到哪一步。一线还要会读connection_name应用日志打印同一名字Broker list_connections 才能对上。没有名字的排障会退化成「重启所有支付 pod」。把命名规范写进脚手架和第 11 章户口一起验收。日志里搜 reply-code 数字比搜中文「失败」准。把 403/404/406/541 做成日志字段而不是埋在异常 toString 里随版本变化。给新值班的十分钟教案先背口诀再在实验室把 A 和 C 亲手跑一遍D 看一眼 consumers 列E 只看第 14 章录像不必真拧水位。一周内完成 B 的权限拒绝。通过标准是不靠重启能说出下一步命令。第 16 章综合实战会假设这张检查单已经存在缺表就无法验收通知中心。把回复码对照表打印给开发当书签看到 406 先想声明冲突不要先想「Broker 版本不对」。看到 404 先想 VHost 过滤器与名字拼写不要先重启。看到 403 先想第 11 章正则。内部错误 541 才升级到运维看 logs。升级路径清楚工单才不会全部堆成「MQ 挂了」。一线处理时限A/B/C 十五分钟内应定位到配置或代码D 十分钟内确认消费者进程E 按第 14 章时间线。超时未定位则升级而不是开始随机重启。日志字段建议ts、level、connection_name、vhost、user、reply_code、queue。缺字段的接入方要补。测试在故障用例里断言应用日志出现对应 reply_code形成闭环。没有闭环SOP 只是墙上的纸。第 16 章会要求通知中心演示至少注入 A、C、D 各一次并当场对照检查单打勾。准备不齐不要开演示会。sysmon 日志出现 busy_dist_port 一类信息时先记下不必在基础篇深挖转到中级性能章。但一线要知道「这不是应用 HTTP 500 的同一类东西」避免把 Erlang 内部事件当业务异常发版回滚。分诊的最后一层才是运行时内部。周五晚值班允许的操作集合要白名单化list、ping、alarms、kick 指定 user 的连接、set_log_level 并设闹钟改回。不在白名单的down -v、删 VHost、clear_operator_policy、随意 Purge 支付队列。白名单贴在群公告。越权操作即使救了场也要复盘。测试的故障包不得要求执行白名单外命令。这样实验室与生产的操作集收敛第 16 章演示也不会当众删数据。常见回复码表要在入职培训默写 403/404/406。默写不出的人上线前补课。这不是形式主义而是减少「MQ 不行了」工单的最快方法。把默写卷存档听起来可笑但比事故后读这一章便宜。基础篇结束时开发应能不看文档说出 406 与通道隔离的关系运维应能不看文档说出红灯先看消费者。做不到就还没准备好综合实战。3.9 完整代码清单column/samples/ch15/fault_connect.py column/samples/ch15/fault_406.py column/samples/ch15/checklist.md column/samples/ch15/baseline.sh4. 项目总结优点与缺点做法优点缺点分诊式 SOP少误重启、可测试要训练急了仍想拉闸一律重启 Broker简单扩大事故、丢确认窗口只看 UI直观无自动化、手滑 Purge只看应用日志近代码不见 alarms/listeners优点1五种病可回归。2回复码与章节交叉引用。3测试与运维共用一张表。缺点1单机 SOP 覆盖不了脑裂。2debug 日志有副作用。3客户端乱关连接会掩盖通道级故障。适用场景值班一线、测试混沌、新环境验收。第 16 章综合实战的故障注入。开发解读 AlreadyClosed 前先对 reply-code。不适用用本章代替集群排障用 aliveness 每秒打把down -v当清理。注意事项先 ping/alarms 后重启。406 后检查连接池策略。日志级别有时限。安全排障账号不要长期 administrator。版本4.x 废弃特性错误文案与 3.x 不同不要用旧博客搜 406。常见踩坑生产连不上先重启 Broker其实是应用配错 VHost。根因无分诊。406 关闭整池支付全停。根因第 4 章隔离没做。debug 忘关打满磁盘变成病例 E。根因日志无时限。思考题如何用测试框架把 SOP-AE 编排成「一条失败不污染下一条」的夹具含水位恢复NOT_FOUND交换机与「发到存在的交换机但 routed false」在日志和客户端表现上如何区分值班各问哪一句第 16 章综合实战会用到检查单题 1 的夹具可在第 16 章实现。附录 C第 14 章思考题参考答案题 1为何集群范围停写。内存/磁盘告警按节点资源传播任一节点告警则各节点发布都应停避免流量打向「看起来还好」的节点继续把集群拖死。经典队列本身不复制停写保护的是该节点进程和磁盘quorum 虽有副本成员所在节点内存爆了同样救不了 Raft 追加。细节到第 17、19 章但一线 SOP 仍是见 Alarm 先停发。题 2无消费者能否自动解除内存告警。不能单靠停发布。内存被已在队列里的消息、unacked、连接占着必须消费、TTL、丢弃或 Purge后者伤数据。SOP 要「拉起消费者或有控制地泄洪」不是傻等红灯自己灭。延伸阅读与资源SQLAlchemy 2.0从入门到进阶的实战之旅Dify 从入门到进阶LLM 应用平台实战修炼Java 工程师进阶从 JVM 生产排障到OpenJDK原理NumPy 从入门到生产落地全链路实战指南科学计算/向量化Redis 8 实战精讲从 CRUD 到源码构建高可用缓存系统Redis 实战修炼与原理进阶Python 3实战精进从脚本到高并发订单引擎python入门Rquests从菜鸟脚本到企业级SDK的网络实战圣经Milvus向量数据库实战修炼从 0 到 1精通向量检索与生产落地MongoDB 实战进阶与内核修炼后端工程师的 AI 转型第一课Ollama 与私有化大模型实战10倍开发者的 Dify 魔法书从零构建全栈 AI 应用后端工程师转型AI第一课-Ollama 与私有化大模型实战大型语言模型(LLM) vLLM 高性能推理落地实战Agent开发之LlamaIndex 实战修炼与源码进阶大语言模型Transformers 实战修炼与源码剖析
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。