ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

RabbitMQ测试工具全解析:从连通性检查到压测实践

RabbitMQ测试工具全解析:从连通性检查到压测实践 简介RabbitMQ测试工具是一款基于WPF开发的桌面应用面向需要在本地或远程环境中调试、监控消息队列的开发与运维人员解决连接配置、队列浏览、交换机管理及路由排查等常见问题。工具覆盖连接管理、集群节点监控、队列与交换机操作、绑定可视化、模板消息发送、日志跟踪及AMQP/API调用能力适用于开发调试、性能验证、系统监控和故障诊断等场景。压缩包共9个文件包含exe主程序、动态库及配套xml配置文档、ini设置文件与pdb调试信息整体仅336KB便携易用。目前已有1752人学习下载适合正在使用RabbitMQ构建分布式系统、需要快速验证消息收发或排查路由异常的初中级开发者。借助绑定关系图和预置消息模板读者可直观理解消息流转路径并基于内置接口示例提升对RabbitMQ管理与调优的实操能力。1. RabbitMQ 测试工具没有统一答案先分清是测连通、测功能还是测并发我接手过一个非常典型的排查运维说 RabbitMQ 连接正常开发说消费端就是收不到消息两边用的“RabbitMQ 测试工具”根本不是同一个东西——一个是 telnet 一下 5672 端口另一个是盯着管理界面看队列数字。这种分歧其实说明了一个问题测试 RabbitMQ 到底是测协议连通、测消息流转逻辑还是测吞吐稳定性三种目标的工具链完全不同。docker exec 进容器跑一条 curl和拿压测脚本打十万条消息都是“RabbitMQ 测试工具”的一部分差别只在于你要回答哪个问题。这篇笔记把这个问题拆开讲清楚适合刚把 RabbitMQ 引入项目、正在搭测试环境的团队也适合被“服务在跑但消息不动”这类玄学问题反复折磨的人。2. 测试工具选型为什么 rabbitmqadmin、管理界面、perf-test 各管一段2.1 三类测试目标决定你该碰哪个工具消息队列测试不是“发一条消息看有没有收到”这么简单要把协议层、路由层、消费语义层分开看。按落地顺序我习惯分成三类连通性与环境状态测试功能与消息流转测试性能与稳定性测试。它们分别解决“服务在不在”“逻辑对不对”“扛不扛得住”三个问题。这也是为什么很多人搜到 RabbitMQ 测试工具教程却觉得对不上号——教程讲的可能是 rabbitmqadmin 发消息但你实际需要的是压测参数。连通性测试关注的是 Erlang 节点是否起来、5672 和 15672 端口是否可达、账号密码能不能通过认证、指定 vhost 是否可访问。这类测试不关心消息内容甚至不关心有没有队列存在能 ping 通就算通过。功能测试则要覆盖交换器类型、绑定关系、路由键匹配、死信转发、手动 ack 和 requeue、TTL 和优先级这一类行为。性能测试关心吞吐量、延迟、连接数、消息积压水位、内存和磁盘告警。这三类目标对工具的形态要求完全不一样。连通性测试一条 curl 就够功能测试最好有个能反复执行、能断言的脚本入口性能测试则需要专门的流量发生器。选型之前先把目标定下来否则很容易出现“装了工具但帮不上忙”的情况。这和 kafka、rabbitmq、rocketmq 这类消息队列选型是一个道理先列出你的对比条件再谈具体技术不然只会陷入工具与工具之间的无效对比。2.2 各工具到底管哪一段Web 管理界面也就是 15672 端口的那个页面适合人肉观察队列积压、连接数、Channel 数、内存水位和消费者状态。它最大的价值是“看”不适合做自动化断言也经不起频繁点击操作。它还有一个隐藏用途管理界面能打开说明管理插件和 HTTP API 这一层是通的这是排查时的重要分界线。rabbitmqadmin 是管理插件自带的 Python 脚本等于把 HTTP API 封装成了命令行。它适合快速声明队列、绑定交换器、发布消息、取消息也适合写进冒烟脚本里。它不依赖 Erlang 环境只要有 15672 端口就能用这是它比 rabbitmqctl 更适合做功能测试的原因。rabbitmqctl 是节点控制工具负责账号、vhost、权限、节点诊断两者分工不同不能互相替代。HTTP API 是自动化测试的主干。任何语言都能直接调RabbitMQ 管理插件暴露了 /api/queues、/api/exchanges、/api/bindings、/api/connections 这一组接口队列深度、消息速率、消费者数量都能用 JSON 取回来。与其专门去找一个接口测试工具不如把 HTTP API 当作接口测试工具的一部分来用它天然支持 curl也天然能被 CI 集成。rabbitmq-perf-test 是官方压测工具一个 Java 可执行包也有容器镜像。它负责持续生产消息、持续消费消息测吞吐和延迟。它和功能测试工具的边界很清晰你要验证逻辑对不对用 rabbitmqadmin 或代码客户端你要验证发版后扛不扛得住用 perf-test。最后是代码级客户端包括 pika、amqp 这类库它们最贴近生产代码的真实路径能完整模拟手动 ack、nack、死信、重新入队这些语义。2.3 最小够用组合日常功能测试加压测两套就够很多团队上来就搭一套复杂的测试平台其实没必要。消息队列的测试工具不是越多越好够用即可。我一般推荐两套组合日常功能测试用 rabbitmqadmin 加 HTTP API发版前用 perf-test。CI 里则用代码客户端或 curl 脚本做断言回归。现在 AI 测试工具讨论很热但消息队列这种带状态的中间件测试价值恰恰体现在和“时间”“确认”“路由状态机”相关的行为上通用 AI 工具很难替代这种协议级验证。下面这张表是我做选型时常用的对照重点看“自动化程度”和“职责”两列。工具负责哪一段自动化程度选型注意管理界面人肉观察状态不可自动化不能当断言工具用rabbitmqadmin快速声明、发布、取消息适合脚本化等同于 HTTP API权限规则同 APIHTTP API自动化断言、状态检查完全可自动化vhost 要 URL 编码rabbitmq-perf-test吞吐、延迟、稳定性压测可脚本化注意心跳和队列类型代码客户端集成测试、语义回归完全可自动化手动 ack 是坑源选择的标准就一条这个工具回答的是哪一层的问题。管理界面说“队列有积压”rabbitmqadmin 可以立刻取一条消息看内容HTTP API 可以断言“积压量应该归零”perf-test 可以回答“这个量级的积压下系统还稳不稳”。工具之间不是替代关系而是各管一段。3. 用 Docker 拉起 RabbitMQ 测试环境镜像参数、virtual host 与权限初始化3.1 最小落地rabbitmq:4-management 镜像与端口映射测试 RabbitMQ 的第一步是有一个可复现的环境。最省事的方式是用 Docker 跑一个带管理插件的镜像镜像标签带上 management 就表示已经启用管理插件不需要再手动 rabbitmq-plugins enable。生产如果还在 3.13.x测试环境建议跟随生产大版本避免出现 3.x 与 4.x 行为差异导致的误判。自建测试环境我一般直接用 rabbitmq:4-management因为 4.x 对 quorum queue 的支持更完整而生产迟早会往这个方向走。services: rabbitmq: image: rabbitmq:4-management container_name: rabbitmq-test hostname: rabbitmq-test restart: unless-stopped ports: - 5672:5672 - 15672:15672 - 25672:25672 environment: RABBITMQ_DEFAULT_USER: testadmin RABBITMQ_DEFAULT_PASS: Test123456 RABBITMQ_DEFAULT_VHOST: /qa RABBITMQ_ERLANG_COOKIE: test-cookie-only healthcheck: test: [CMD, rabbitmq-diagnostics, ping] interval: 15s timeout: 10s retries: 5端口映射里 5672 是 AMQP 协议端口客户端的连接都走这里15672 是管理插件端口Web 管理界面和 HTTP API 都用它25672 是集群节点间通信端口单机测试不一定需要但映射出来有助于在本地模拟多节点场景。hostname 这个参数容易被忽略RabbitMQ 的节点名基于主机名如果不固定 hostname容器每次重建后节点名都会漂移测试环境里如果挂载了数据目录后续排查会非常痛苦。healthcheck 用 rabbitmq-diagnostics ping这个命令检查的是 Erlang 节点是否活着比单纯检查端口要可靠。环境变量里的 RABBITMQ_DEFAULT_USER、RABBITMQ_DEFAULT_PASS、RABBITMQ_DEFAULT_VHOST 会在节点启动时自动创建对应账号和 vhost。但要注意默认创建出来的用户只对这个默认 vhost 有权限并不天然具备全局管理员权限这往往是后面坑的源头后面专门讲。3.2 rabbitmqctl 一次性初始化账号、vhost 和权限测试环境的账号规划比生产简单但权限模型必须和生产一致。常见做法是为测试专门创建一个账号和独立 vhost避免把生产账号拖进测试链路。下面这套命令适用于新的测试环境初始化场景。docker exec -it rabbitmq-test rabbitmqctl add_user qa_user Qa#2024 docker exec -it rabbitmq-test rabbitmqctl set_user_tags qa_user monitoring docker exec -it rabbitmq-test rabbitmqctl add_vhost /qa_1 docker exec -it rabbitmq-test rabbitmqctl set_permissions -p /qa_1 qa_user ^.* ^.* ^.*第一行创建账号第二行打标签第三行建 vhost第四行授权。set_user_tags 后面的 monitoring 标签只表示这个用户能通过 HTTP API 查看监控数据没有创建 vhost 的权限。如果测试环境只有一个人用直接给 administrator 标签最快但如果你在模拟多角色分工可以按 monitoring 和 policymaker 这类标签分开给。set_permissions 后面的三个参数依次是 configure、write、read分别对应声明和删除队列、发布消息、消费消息。业务账号一般建议给全三项但压测专用账号可以只给 write 和 read。推荐的 always 检查是把刚才的授权结果再列一遍可以防手滑docker exec -it rabbitmq-test rabbitmqctl list_permissions -p /qa_1这里要理解一个容易踩的模型RabbitMQ 的权限是“vhost 维度 资源正则”的结构。set_permissions 后面的三个正则分别控制哪些资源名允许 configure、write、read。^.* 表示所有资源如果只允许 test.q 这个队列就写成 ^test.q$。测试环境图省事都用全匹配但至少要意识到这个粒度。3.3 两路连通性验证AMQP 5672 与 HTTP 15672环境起来之后第一件事不是写业务代码而是验证两个链路AMQP 协议链路和 HTTP 管理链路。这两个链路一个是业务数据走的通道一个是运维和断言走的通道任何一条不通后面的测试工具都用不了。docker exec -it rabbitmq-test rabbitmq-diagnostics -q ping docker exec -it rabbitmq-test rabbitmq-diagnostics check_running curl -s -u testadmin:Test123456 http://localhost:15672/api/overview | python3 -m json.tool | head -20第一条 ping 是 Erlang 节点层面的存活检查第二条 check_running 是节点内部应用是否全部启动第三条是管理插件端口是否返回正常 JSON。前两条在容器内执行适合 docker logs 之前做初步判断第三条在宿主机执行验证端口映射和认证是否生效。如果第三条返回 401说明不是端口问题而是账号问题如果超时说明 15672 没映射出来或者管理插件没就绪。AMQP 链路的验证不需要写业务代码用一个简单的 Python 脚本就能测。注意这只是一个探针不承担任何功能测试职责。import pika params pika.URLParameters(amqp://testadmin:Test123456localhost:5672/%2Fqa) conn pika.BlockingConnection(params) chan conn.channel() chan.queue_declare(queueprobe.q, durableTrue) chan.basic_publish(exchange, routing_keyprobe.q, bodybprobe) print(chan.queue_declare(queueprobe.q, passiveTrue).method.message_count) conn.close()验证思路是能建连接、能声明队列、能发消息、能查到消息数说明 AMQP 链路没问题。routing_key 用空字符串表示走默认交换器消息直接进指定队列。这里没有消费和生产逻辑纯粹探活跑通了就说明环境是可测试的。4. 功能测试高频操作rabbitmqadmin 与 HTTP API 的断言套路4.1 rabbitmqadmin 的安装与常用命令清单rabbitmqadmin 不需要单独下载安装包它是管理插件自带的脚本直接从管理端口拉下来就能用。很多 rabbitmq 安装教程里提到 rabbitmqadmin但默认镜像不带这个脚本这一步需要自己执行。curl -s http://localhost:15672/cli/rabbitmqadmin /usr/local/bin/rabbitmqadmin chmod x /usr/local/bin/rabbitmqadmin rabbitmqadmin --version如果你的机器上 Python 环境比较旧可能跑不起来因为管理插件新版本对 Python 版本有要求。Windows 环境下没有 /usr/local/bin可以下载后用 python rabbitmqadmin 直接执行。这个脚本本质上是对 HTTP API 的一层封装所以它支持的操作用 curl 都能实现但命令行形式在快速操作时明显更顺手。rabbitmqadmin 的常用命令集中在声明、发布、取回这三类操作上。声明队列、声明交换器、建立绑定这是功能测试前的准备动作发布消息是触发被测逻辑取消息是验证消费结果。下面的命令串是一条典型的“建队列、建交换器、绑路由、发消息”链路。rabbitmqadmin -H localhost -P 15672 -u testadmin -p Test123456 \ declare queue nametest.q durabletrue rabbitmqadmin -H localhost -P 15672 -u testadmin -p Test123456 \ declare exchange nametest.ex typedirect durabletrue rabbitmqadmin -H localhost -P 15672 -u testadmin -p Test123456 \ declare binding sourcetest.ex destinationtest.q routing_keyorder.created rabbitmqadmin -H localhost -P 15672 -u testadmin -p Test123456 \ publish exchangetest.ex routing_keyorder.created payload{orderId:1001}注意 declare binding 后面的参数source 是交换器名destination 是队列名routing_key 是绑定的路由键。很多初学者会把 binding 参数和消息发布的 routing_key 搞混它们是两回事声明绑定时 key 决定哪些消息能进这个队列发布时 key 决定消息去哪。payload 参数就是消息体默认按字符串发送。取消息用 get 命令这是功能测试里最常用的验证手段。它的设计语义和 HTTP API 里的 get 操作一致直接从一个队列里取消息而不是走消费者订阅。rabbitmqadmin -H localhost -P 15672 -u testadmin -p Test123456 \ get queuetest.q count5 ackmodeack_requeue_falseget 命令的关键参数是 ackmode。ack_requeue_false 表示把消息取走并从队列中删除适合验证消息确实被消费的场景ack_requeue_true 表示取出来看一眼再放回队列适合检查消息内容但不销毁消息的场景。测试断言里基本都用 false调试场景用 true 会更多。4.2 用 HTTP API 验证队列状态与消费结果rabbitmqadmin 适合人肉敲命令但 CI 和脚本化断言需要的是 HTTP API。管理插件暴露的 /api/queues 接口返回 JSON里面的 messages、messages_ready、messages_unacknowledged 分别代表队列总消息数、待消费消息数、已投递但未确认消息数。这三个字段是功能测试断言的核心。curl -s -u testadmin:Test123456 \ http://localhost:15672/api/queues/%2Fqa/test.q | \ python3 -c import sys,json; djson.load(sys.stdin); print(messages, d[messages], ready, d[messages_ready], unacked, d[messages_unacknowledged], consumers, d[consumers])这里最容易出错的是 URL 里的 %2Fqa。vhost 在 HTTP API 路径中是 path 的一部分必须做 URL 编码默认 vhost 是 /编码后就是 %2F。如果你有多级 vhost比如 /qa/env1就要写成 %2Fqa%2Fenv1。直接拿未编码的 vhost 去请求API 会返回 404。management UI 能打开但 admin 用户不能创建虚拟主机这种问题往往也是权限和路径两个因素叠加造成的。断言思路一般是三段式发布前队列为空发布 N 条后 messages 等于 N消费或 get 之后 messages 归零。下面这个命令在发布后执行可以验证路由结果是否正确。curl -s -u testadmin:Test123456 \ http://localhost:15672/api/queues/%2Fqa/test.q | \ python3 -c import sys,json; djson.load(sys.stdin); assert d[messages] 2, d[messages]; print(ok)如果这里 messages 不是 2说明交换器类型、绑定关系、路由键三个环节至少有一个错了。先用 rabbitmqadmin list queues 确认队列存在再 list bindings 确。续写挂掉的消费者、绑定键对不对比直接去查代码快得多。4.3 一个“发布-断言-消费”的完整测试脚本把前面的命令拼起来就是一个可以在 CI 里跑的冒烟脚本。它的价值在于把“环境是否就绪、路由是否正确、消息是否可消费”全部验证完任何一步失败都能直接指向问题层。下面是一个我常用的最小脚本模板。#!/usr/bin/env bash set -euo pipefail BASEhttp://localhost:15672 AUTH-u testadmin:Test123456 VHOST%2Fqa QUEUEsmoke.q # 清理上一次残留保证断言起点干净 curl -s $AUTH -X DELETE $BASE/api/queues/$VHOST/$QUEUE || true sleep 1 # 重建队列durabletrue 保证声明语义和生产一致 curl -s $AUTH -X PUT $BASE/api/queues/$VHOST/$QUEUE \ -H content-type: application/json -d {durable:true} # 发布两条消息走默认交换器直接进队列 curl -s $AUTH -X POST $BASE/api/exchanges/$VHOST/amq.default/publish \ -H content-type: application/json \ -d {routing_key:smoke.q,payload:hello-1} curl -s $AUTH -X POST $BASE/api/exchanges/$VHOST/amq.default/publish \ -H content-type: application/json \ -d {routing_key:smoke.q,payload:hello-2} # 等待消息落盘断言队列里正好两条 sleep 1 MSGS$(curl -s $AUTH $BASE/api/queues/$VHOST/$QUEUE | \ python3 -c import sys,json; print(json.load(sys.stdin)[messages])) [ $MSGS 2 ] || { echo expected 2, got $MSGS; exit 1; } # 取走一条消息并确认断言剩一条 curl -s $AUTH -X POST $BASE/api/queues/$VHOST/$QUEUE/get \ -H content-type: application/json \ -d {count:1,ackmode:ack_requeue_false,encoding:auto} sleep 1 MSGS$(curl -s $AUTH $BASE/api/queues/$VHOST/$QUEUE | \ python3 -c import sys,json; print(json.load(sys.stdin)[messages])) [ $MSGS 1 ] || { echo expected 1, got $MSGS; exit 1; } echo smoke ok第一段清理是为了保证断言起点干净因为测试队列可能被上一次跑挂的用例留下残留消息。重建队列用 PUT 方法这是管理插件定义的上游 API 语义重复执行是幂等的。发布消息走 amq.default注意路径中的 vhost 仍然是编码后的还有 amq.default 这个名字里的点不需要转义。取出消息后用 ackmodeack_requeue_false消息不会被放回队列这样最终断言才准确。这个脚本如果跑通意味着环境、权限、队列声明、消息投递、消费确认这五个环节全部正常可以作为“服务是否可测”的统一判据。5. RabbitMQ 测试工具最常见的 5 个坑与排查记录5.1 管理界面能打开但 admin 用户创建不了 virtual host现象docker 部署 rabbitmq 之后用浏览器访问 15672 管理界面登录正常队列列表也能看到但点击添加 virtual host 时一直失败或者在管理界面里创建队列提示权限不足。很多人在这里就开始怀疑是不是 admin 账号密码有问题。原因这个场景在 Docker 部署 RabbitMQ 后非常典型。通过 RABBITMQ_DEFAULT_USER 创建出来的用户并不自动带 administrator 标签它只是对 RABBITMQ_DEFAULT_VHOST 这个特定 vhost 有权限。创建 virtual host 是全局管理操作需要 administrator 标签或者至少拥有根 vhost 的 configure 权限。界面能登录只能说明认证通过不代表授权够。解决用 rabbitmqctl 给用户补上 administrator 标签然后重新授权。docker exec -it rabbitmq-test rabbitmqctl set_user_tags testadmin administrator docker exec -it rabbitmq-test rabbitmqctl set_permissions -p /qa testadmin .* .* .*建议把 RABBITMQ_DEFAULT_USER 做成管理员再单独创建业务账号。这样测试环境里有一个最高权限账号兜底业务账号按最小权限分配排查权限问题时有清晰的参照物。5.2 容器显示运行中但 5672 端口就是不监听现象docker ps 里容器状态是 Up但客户端连接 5672 报 connection refused管理界面也可能打不开docker logs 一直刷异常或重启记录。这是 rabbitmq 启动失败最常见的呈现方式。原因分两类。一类是环境问题比如宿主机 5672 端口被占用或者 Docker 端口映射写错。另一类是 RabbitMQ 自身启动失败常见原因包括容器 hostname 变化导致 mnesia 数据目录定位异常内存不足触发启动保护或者挂载的数据目录没有写权限。在 4.x 版本里节点启动过程比旧版更慢容器显示 Up 并不代表 Erlang 应用已经就绪这里存在一个十几秒到几十秒的“假 Up”窗口。解决不要看 docker ps直接看 docker logs 和诊断命令。docker logs rabbitmq-test --tail 100 docker exec -it rabbitmq-test rabbitmq-diagnostics -q ping docker exec -it rabbitmq-test rabbitmq-diagnostics check_running curl -s -u testadmin:Test123456 http://localhost:15672/api/health/checks/alarms第一条看有没有报错堆栈第二条确认 Erlang 节点是否活着第三条确认应用是否加载完第四条确认系统是否进入告警状态。如果 ping 通但 check_running 失败说明节点起来了但应用没就绪继续等即可。如果 ping 都失败重点检查 hostname 和数据目录。另一个隐蔽情况是内存告警时 RabbitMQ 会阻塞所有生产连接表现上也是连接异常需要执行 rabbitmq-diagnostics memory 看是否达到高水位或者干脆把测试容器的内存限制调高。5.3 rabbitmqadmin 报 401 或 connection refused现象rabbitmqadmin 在服务器本机执行没问题但从 CI 机器或自己电脑上跑换来的是 401 Unauthorized或者干脆 connection refused。这个坑在本地开发和远程环境之间切换时特别容易出现。原因rabbitmqadmin 默认连接 localhost:15672远程执行时必须显式指定 -H。401 则是账号密码或权限问题字符串里的特殊字符没加引号或者对目标 vhost 没有相应权限。第三个原因也是容易被忽略的拿到的 rabbitmqadmin 版本和服务器管理插件版本不一致不同版本之间参数和 API 会有细微变化。解决远程执行时把主机、端口、账号、密码四个参数全部显式写上不要在命令行里依赖默认值。密码包含特殊字符时用单引号包裹。版本不一致时直接无条件从目标服务器的 /cli/rabbitmqadmin 重新下载确保脚本和 API 完全配套。另外可以通过检查 HTTP API 来定位如果 /api/overview 能返回 JSON那问题一定出在脚本参数上而不是网络或服务。curl -s -u testadmin:Test123456 http://remote-host:15672/api/overview5.4 压测时连接被断开heartbeat 与内存告警现象用 perf-test 或自研压测脚本跑一段时间后客户端报 connection reset或者连接被服务端关闭日志里出现 missed heartbeats。队列里消息在堆积管理界面的内存条变成红色。原因两个主要原因叠加。第一RabbitMQ 默认心跳超时时间较短客户端如果长时间忙于本地处理或 GC没来得及发送心跳帧服务端就判定连接失效并主动关闭。压测场景里消费者处理慢、积压增大最容易触发心跳超时。第二内存高水位告警触发后RabbitMQ 会阻塞连接上的生产者客户端表现为连接被卡死或异常断开。解决压测前把心跳参数显式配置别用默认值。同时检查内存告警阈值给压测环境留足余量。java -jar rabbitmq-perf-test.jar \ --uri amqp://testadmin:Test123456localhost:5672/%2Fqa \ --queue perf.q \ --producers 2 \ --consumers 2 \ --time 60 \ --heartbeat 60perf-test 的 --heartbeat 参数控制客户端发送心跳的间隔心跳值越大越不容易被误杀但也不能太大否则服务端无法及时感知客户端失效。一般设为 60 到 120 秒即可。内存告警方面可以临时调高容器内存也可以调整高水位比例但作为测试工具链的一员最该做的是把堆积量控制在合理范围用足够的消费者把并发吃掉而不是靠修改服务端阈值来掩盖问题。5.5 Unacked 消息越积越多消费确认的测试陷阱现象管理界面里某个队列的 messages_ready 在下降但 messages_unacknowledged 一直在涨和 consumers 数量完全不成比例最终积压到告警。消费者看起来还连着消息却一直不被确认。原因这是功能测试里最容易翻车的地方。测试消费者用手动 ack但业务逻辑走某个分支后没有 ack也没有 nack 或 requeue。比如处理消息时抛了异常但没有 catchack 语句永远执行不到。另一个常见原因是 prefetch 设得过大消费者一次性拉了几千条消息到本地处理速度跟不上服务端只能把后面所有消息都标记为 unacknowledged。在测试场景里你为了模拟真实消费逻辑手动 ack 往往是必须的但一旦没控制好 prefetch整个队列状态就看起来像“死”了一样。解决先确认是不是消费者逻辑问题还是纯粹测试姿势问题。检查 unacknowledged 数量和消费者列表能快速定位。docker exec -it rabbitmq-test rabbitmqctl list_queues name messages messages_ready messages_unacknowledged docker exec -it rabbitmq-test rabbitmqctl list_consumers queue_name channel_pid prefetch_count第一条看哪个队列积压第二条看每个消费者的 prefetch 设置。如果确认是测试消费者没有 ack就给消费者手动补一条 ack 路径或者在异常分支里统一走 basic_nack 加 requeuefalse。如果只是测试环境需要清掉积压直接用 rabbitmqadmin get 加 ackmodeack_requeue_false 把消息全部取走即可不必关心消费者逻辑。但如果在压测场景里出现 unacked 持续上涨就要把 prefetch 降下来比如从 1000 降到 100让负载在多个消费者之间摊开这个数值往往比并发数更关键。6. 进阶技巧一个脚本把“发到消费”的闭环验证固化下来6.1 用 bash 加 curl 完成 publish、断言、consume 冒烟测试前面说过 rabbitmqadmin 的 get 命令可以取消息但真正的测试闭环应该包含“发布、断言、消费、再断言”四个步骤。下面这段脚本把冒烟测试固化成一条命令环境变更后跑一遍能快速确认 RabbitMQ 测试工具链里所有关键环节是否正常。#!/usr/bin/env bash set -euo pipefail BASEhttp://localhost:15672 AUTH-u testadmin:Test123456 VHOST%2Fqa QUEUEsmoke.q curl -s $AUTH -X DELETE $BASE/api/queues/$VHOST/$QUEUE || true curl -s $AUTH -X PUT $BASE/api/queues/$VHOST/$QUEUE \ -H content-type: application/json -d {durable:true} curl -s $AUTH -X POST $BASE/api/exchanges/$VHOST/amq.default/publish \ -H content-type: application/json \ -d {routing_key:smoke.q,payload:hello-1} sleep 1 MSGS$(curl -s $AUTH $BASE/api/queues/$VHOST/$QUEUE | \ python3 -c import sys,json; print(json.load(sys.stdin)[messages])) [ $MSGS 1 ] || { echo expect 1, got $MSGS; exit 1; } curl -s $AUTH -X POST $BASE/api/queues/$VHOST/$QUEUE/get \ -H content-type: application/json \ -d {count:1,ackmode:ack_requeue_false,encoding:auto} sleep 1 MSGS$(curl -s $AUTH $BASE/api/queues/$VHOST/$QUEUE | \ python3 -c import sys,json; print(json.load(sys.stdin)[messages])) [ $MSGS 0 ] || { echo expect 0, got $MSGS; exit 1; } echo smoke ok这段脚本和前面 4.3 的区别是更精简它不测路由绑定只测“发布能进队列、消息数可读、get 能消费确认”适合当作环境自检脚本。发布走默认交换器所以不涉及交换器绑定也减少了外部依赖。每次执行先删队列再重建保证结果可重复。这里用 Python 解析 JSON如果不想依赖 Python可以用 jq 替代但 jq 在 CI 镜像里不一定是预装的。6.2 顺手把 perf-test 的冒烟参数固化成脚本功能测试闭环能证明消息流转正确但证明不了系统能扛多少流量。我现在的习惯是在 CI 里加一个极轻量的 perf-test 冒烟任务不开全量压测只跑 30 秒确认吞吐不为零、连接稳定防止基础设施变更导致性能回归。java -jar rabbitmq-perf-test.jar \ --uri amqp://testadmin:Test123456localhost:5672/%2Fqa \ --queue perf-smoke.q \ --producers 2 --consumers 2 \ --time 30 \ --qos 200 \ --heartbeat 60qos 参数对应 channel 的 prefetch 计数200 是一个不容易把内存打爆的保守值。生产者两个消费者两个30 秒时间跑完看输出里的 throughput 和 latency如果吞吐接近零或latency持续上涨就要怀疑环境是否有问题。这个脚本不追求测出极限只负责在发版前快速拦截“完全不可用”级别的回归真正的压测再单独安排长任务。我现在的习惯是先把冒烟脚本跑通再碰任何业务相关的测试工具。如果这个脚本立的“环境、权限、队列、发布、消费”五件事都过不了后面所有测试都不可信。这个习惯帮我省下了很多排查时间也希望帮到你。本文还有配套的精品资源点击获取
返回列表