首页 / 资讯中心 / 文章详情

JMeter压测RabbitMQ:从AMQP协议到性能测试完整方案

JMeter压测RabbitMQ:从AMQP协议到性能测试完整方案 ★ FEATURED ARTICLE
简介面向需要评估RabbitMQ高并发生产与消费性能的测试开发工程师这份压缩包提供了基于Apache JMeter的完整压测方案覆盖消息中间件在压力场景下的吞吐量、响应时间与资源占用摸底也适用于容量规划和瓶颈定位。整个压缩包共2881个文件、大小约53MB主要文件类型包括HTML帮助文档、PNG界面截图、JavaScript与CSS前端资源、JAR插件包、JMX测试计划、TXT配置说明还包含JMeter启动脚本、BeanShell断言与采样器脚本并带有参数化、属性及CSV数据文件目录结构完整便于按需提取和修改。目前已有1854人学习下载。包内JMX示例可直接导入JMeter使用快速搭建生产者与消费者测试场景配置交换机、队列、虚拟主机等连接参数配合聚合报告、响应时间图等监听器观察关键指标支持CSV参数化模拟不同消息内容也能扩展为分布式负载测试帮助验证多机并发下的稳定性与可靠性。此外HTML文档和截图对插件安装、采样器选项及常见问题做了直观说明降低了上手门槛适合初学或已具备一定压测经验的读者直接复用。1. 从压测脚本到完整方案这个压缩包解决的是 RabbitMQ 性能测试的最后一公里做消息中间件压测的人多半经历过这种尴尬JMeter 装好了、RabbitMQ 管理台也开着想模拟几千条消息同时打进去却发现原生 JMeter 压根不认 AMQP 协议。翻遍插件市场找到的 Sampler 要么版本老旧要么连不上 RabbitMQ 3.x 的认证机制。apache-jmeter-rabbitMQ测试.zip 这种命名看起来平平无奇但它本质上是一个把 JMeter、AMQP 客户端库、测试脚本和参数配置打包好的完整方案——解压后不是让你看 README 的是让你直接跑出吞吐量数据的。对正在做消息推送、异步任务削峰、延迟队列性能评估的从业者来说这份资源的价值在于帮你省掉从零摸索协议插件和踩认证坑的两三天时间适合需要快速得到 RabbitMQ 压测基线数据的开发者或测试工程师。2. JMeter 为什么要靠外部方案才能测 RabbitMQ协议缺口与三套常见选型2.1 JMeter 原生不支持 AMQP 的根因HTTP 之外的协议得自己找路JMeter 的核心设计是围绕请求-响应模型做的HTTP、JDBC、FTP 这类协议都能原生支持因为它们的交互模式足够标准化。但 RabbitMQ 走的是 AMQP 0-9-1 协议通信模型是异步的、带 channel 和 exchange 概念跟 JMeter 的 Sampler 执行模型存在本质差异JMeter 发完请求默认要等响应AMQP 发布消息后 broker 只回一个确认帧而且这个确认是异步到达的。官方要把这套协议做成内置 Sampler工作量不小且收益有限所以留给第三方插件和自定义扩展去做。明白这一点你就能理解为什么标题里的压缩包看起来不是单纯拿官方 JMeter 就能搞定的东西——它必然包含额外的客户端库或中间件采样器。常见的补路方案有三种。第一种是装第三方插件如 RabbitMQ Sampler这类插件通常以 jar 包形式放进 JMeter 的 lib/ext 目录用起来像原生 Sampler第二种是自己写 Java Sampler 并编译打包用 maven 管理依赖灵活性最高但门槛也最高第三种是用 JSR223 或 BeanShell 直接在脚本里调用 RabbitMQ 客户端 API这种做法的好处是脚本可见、依赖可控适合团队里没有专职 Java 开发的情况。标题里的 zip 方案通常走的是一二两种的混合路径因为纯脚本方式虽然灵活但在高并发下要做连接池复用和 channel 管理时就力不从心了。2.2 从 zip 包看方案构成依赖、脚本与 JMeter 配置三件套一个面向落地而非教程演示的压测 zip结构上通常会划分成三个部分。第一是依赖包目录里面必须有 amqp-client 的 jarRabbitMQ 官方客户端以及它依赖的 slf4j 日志库slf4j 这步常被忽略缺了它客户端直接抛 NoClassDefFoundError第二是测试脚本目录JMX 后缀的文件区分 JMS Publisher、JMS Subscriber 或纯发布模型第三是配置目录包括 JMeter 的 heap 参数、RabbitMQ 连接参数和线程组参数。如果 zip 里的脚本没有外置参数而是把 IP、端口、vhost 硬编码在 JMX 里那这个包用起来会很难受好在常见做法都会单独放一个 user.properties 或 CSV 数据文件来驱动脚本。我一般拿到这类压缩包先不看脚本内容直接看目录结构和 jar 包版本因为这两个信息能透露方案的新旧和坑位。如果 amqp-client 是 5.x 且 slf4j 单独存在说明配套的是 RabbitMQ 3.8 以上的服务端如果 amqp-client 还停留在 4.x那大概率这个方案是在老版本下编译的配合新 broker 可能出现认证或协议协商问题。另一个看点是 JMeter 版本标识5.x 的 JMeter 用 Java 8 编译而某些旧插件在 5.4 之后的版本会出现 GUI 打不开的现象这些都会影响你能不能把脚本跑起来。2.3 为什么说这个方案的核心竞争力在连接复用而非发送本身RabbitMQ 压测最常见的翻车点是拿阻塞式连接去压并发。每个请求建立一条新连接、开一个 channel、发完就关这种模式在 JMeter 线程数超过 50 之后就会因为 TCP 握手开销把 broker 侧的连接线程池打爆压出来的数据完全是连接开销而非服务端真实处理能力。成熟的打包方案会把连接初始化放到 setUp 线程组用单连接多 channel 或连接池的方式承载并发JMeter 线程组里只做消息发送动作channel 和连接的生命周期由独立机制管理。这也是你在验收一个 zip 方案时最先要确认的点看它是每个 Sample 都做 ConnectionFactory 新建连接还是在 setUp 阶段初始化若干条连接后供线程组共享。前者跑起来像只小水管后者才具备压出吞吐峰值的条件。标题既然带了“测试”二字,方案里通常不会只用默认单连接就跑——那测出来的数字没法指导生产容量规划。3. 把这个方案跑起来从解压到出第一份吞吐报告的最小路径3.1 环境核对与环境变量配置照着做就不会卡在启动阶段动手之前先把环境对齐否则后面一堆诡异报错分不清是脚本问题还是环境问题。JMeter 5.x 要求 Java 8 或 11RabbitMQ 服务端 3.8 或 3.12 都行但要注意一次只测一个版本集群不要把混版集群当压测目标。把 zip 里的 jmeter 目录如果有的话或你自己的 JMeter 安装目录加进 PATH然后核对 Java 版本java -version # 期望输出 openjdk version 1.8.0_xx 或 11.x jmeter -v # 期望输出 Copyright (c) 1999-2021 The Apache Software Foundation # 如果 jmeter 命令找不到检查 JMETER_HOME 环境变量是否指向解压目录注意有些 zip 包不自带 JMeter 二进制只带脚本和依赖这种情况你需要自己准备 JMeter 本体。把 zip 里的 jar 包统一放到$JMETER_HOME/lib/ext下其中 amqp-client 也可以放lib目录但因为 Sampler 需要显式引用类放 ext 更稳妥。检查依赖是否完整可以看 jar 包里有没有com.rabbitmq.client.ConnectionFactory这个类用jar tf命令看一眼即可确认。3.2 连接参数外置把 broker 地址写进属性文件而不是脚本里好的方案会把 broker 参数放在user.properties里JMeter 用__P(propName, defaultValue)函数引用。这种设计有两个好处一是换环境不用打开 JMX 改脚本二是压测脚本本身可以被 CI/CD 平台通过命令行参数动态注入。配置长这样# user.properties 或从命令行 -J 参数传入 # 格式host你的RabbitMQ服务端地址 mq.host192.168.10.20 mq.port5672 mq.vhost/ mq.usernameloadtest mq.passwordloadtest123 mq.queueperf.test.queue mq.exchangeperf.test.exchange mq.routingkeyperf.test.route启动时用jmeter -n -t script.jmx -Jmq.host192.168.10.20 -Jmq.port5672覆盖这样同一个脚本在不同环境跑只需要改命令行参数。脚本内部凡是涉及 broker 地址、端口、vhost 的地方统一用${__P(mq.host,localhost)}这种写法别在 JMX 里硬编码任何环境相关的值。注意 vhost 参数默认是/但很多方案在参数化时会漏掉它导致连接报 530 not-allowed这个是初学者最容易踩的认证坑之一。3.3 用命令行跑压测而非 GUI无头模式才是出报告的正确方式GUI 模式打开脚本确认线程组和 Sampler 配置没问题之后关掉 GUI改用命令行跑。这样做的原因有两个GUI 本身有渲染开销会干扰 JMeter 所在机器的负载曲线另外命令行模式下可以方便地指定报告输出格式和实时汇总间隔。jmeter -n -t rabbitmq-load-test.jmx \ -Jmq.host192.168.10.20 \ -Jmq.port5672 \ -Jmq.usernameloadtest \ -Jmq.passwordloadtest123 \ -l results.jtl \ -e -o /tmp/rabbitmq-report跑完会在/tmp/rabbitmq-report目录下生成 HTML 报告results.jtl是原始采样数据。如果中途想停止CtrlC 会优雅终止但如果连接的 channel 没有正确关闭broker 侧会积压连接告警所以返回去看 RabbitMQ 管理台确认连接是否全释放。对于第一次跑方案建议线程数先设 10循环次数设 100目的是验证链路通不通——消息能不能发到指定 exchange、能不能被消费者接收链路通了再加压力。3.4 验证消息真的进了队列管理台和消费者两侧确认很多人跑完压测只看 JMeter 的 Throughput 数字不看 RabbitMQ 管理台这是把黑匣子当性能数据的典型做法。如果 Sampler 返回成功但消息因为 routing key 不匹配被丢弃或者 exchange 类型错了没绑定队列压测报告里的 TPS 再高也是废数据。所以流程里必须加一步验证# 用 rabbitmqadmin 或管理台查看队列消息数 rabbitmqadmin -H 192.168.10.20 -u loadtest -p loadtest123 \ list queues name messages_ready messages_unacknowledged对照 JMeter 线程组的发送量和队列里的 ready 消息数如果发送 1 万条、队列里 ready 也是 1 万条左右说明消息没有丢失如果 ready 数是 0 且没人消费检查 exchange 绑定关系。这个验证步骤花不了两分钟但能帮你区分“性能差”和“压根没发对”两种完全不同的失败模式。4. 压测参数与模型设计线程数、消息大小和 broker 配置如何影响吞吐曲线4.1 线程组模型选择一锤子并发还是梯度加压JMeter 线程组有三种常见模型直接决定你测出来的是“峰值吞吐”还是“稳态吞吐”。普通线程组在测试开始瞬间把所有线程全拉起来适合测 broker 在突发流量下的表现但如果你想评估 RabbitMQ 在生产中的真实处理能力应该用梯度加压线程组——因为它模拟了流量逐步上涨的过程能让你观察到 broker 在哪个并发点开始出现响应时间拐点。标题方案里如果包含两种线程组第一次跑建议先跑普通线程组看上限再用梯度线程组精确定位拐点。消息量级的设计也有讲究。每条消息默认是 1KB 纯文本但实际业务里可能是几百字节的 JSON也可能是几 MB 的二进制。压测方案应该支持配置消息体大小常见的做法是用随机字符串填充或从 CSV 文件读取真实负载样例。如果压测目标是评估 RabbitMQ 集群的磁盘和内存压力用小消息大量发反而更贴合真实业务如果目标是评估带宽瓶颈那就得用大消息配上更少的并发量这两种跑法结论完全不同务必先想清楚要压哪一层。4.2 必调的四个核心参数与推荐区间把 zip 方案跑通之后接着要动手调的就是下面这四个参数它们对吞吐量和响应时间的影响权重远高于其他配置参数默认值常见方案里推荐设置影响面线程数1梯度测试从 10 起步逐步叠加并发连接与 channel 数量取决于线程组的实现方式消息大小与方案打包时的固定值一致小消息 0.5KB大消息 100KB 以上带宽、磁盘 IO、内存占用全链路放大Publish Confirm 模式不确定默认关压峰值不开压链路可靠性时开开启后吞吐下降 10-20%但能拿到 broker 确认连接复用视方案而定固定连接数通常 5-10 条线程共享 channel连接数过高会顶爆 rabbitmq 的连接线程池线程数这个参数最需要反复试。RabbitMQ 单连接对多 channel 的模式下1000 线程不意味着 1000 条连接而是 1000 个 channel 复用少量连接。如果你的方案是用连接池实现的线程数可以拉到很高而不用担心文件描述符溢出如果方案是每个线程建独立连接那单机建议不超过 300 线程。看方案代码或 README 里对 Connection 和 Channel 的管理方式再决定线程数上限不要盲目拉高。4.3 从吞吐和响应时间曲线反推 broker 状态压测跑到一半打开 RabbitMQ 管理台的 Overview 和 Queues 页面观察几个关键指标队列的 messages_ready 和 messages_unacknowledged 是否在持续增长、连接数是否稳定、Erlang 进程数有没有异常飙高。如果 JMeter 侧吞吐平了但队列消息堆积越来越多说明消费者消化能力跟不上broker 本身没问题问题在消费端如果吞吐曲线和响应时间曲线在某个并发点同时拐头那个点就是当前硬件和配置下的性能上限用这个数据去换算生产环境的容量规划比任何理论估算都可信。一个容易被忽略的细节是 mandatory 和 immediate 标志。如果测试方案里 Sampler 配置了 mandatory 为 true那么当消息无法被路由到队列时broker 会返回 basic.returnJMeter 侧的表现是本次采样失败或延迟异常如果 mandatory 为 false无法路由的消息会被静默丢弃这时吞吐数据完美但消息根本没进队列。跑完压测务必回管理台确认队列里确实有消息这个习惯能避免你拿着假数据去做容量决策。5. 方案落地中的坑与排查五个高频故障让压测结果白跑5.1 连接被拒绝但网络是通的vhost 和认证细节在作怪现象是 JMeter 日志报java.net.ConnectException: Connection refused或者authentication failure但你用 telnet 或 nc 测试端口又是通的。原因多半是 RabbitMQ 默认 vhost 是/而脚本或属性文件里用了别的字符串或者用户没有配置该 vhost 的访问权限。另一个常见原因是 guest 用户默认只能从 localhost 访问如果你从压测机远程连接就算用户名密码正确也报 403。解决方式是新建独立用户并赋权 vhost 权限别动 guest 的默认限制rabbitmqctl add_user loadtest loadtest123 rabbitmqctl set_permissions -p / loadtest .* .* .* # 参数依次是配置、写、读权限生产环境按需收紧如果要从别的机器访问管理台做观察也要确认 management 插件开启且监听地址不是仅限本机。这条排查的价值在于很多初学者在配置阶段就被卡住以为是方案有问题其实只是 RabbitMQ 的默认安全策略在起作用。5.2 压测跑着跑着连接数飙升最后被 broker 踢掉现象是压测中期开始出现大量SocketTimeoutException管理台显示 connection 数量跟线程数量一样多最后 broker 直接拒绝新连接。原因几乎可以肯定是方案里每个线程每次迭代都创建新连接没有走复用逻辑。解决路径有两条如果方案支持连接池配置去属性文件里找pool.size之类的参数调大如果方案不支持就得改脚本把 ConnectionFactory 的连接创建移到 setUp 线程组让多个线程共享同一批连接。改完之后你会看到吞吐量反而稳住甚至上升因为节省下来的 TCP 握手开销全部换成了有效发送能力。5.3 高吞吐下响应时间抖动剧烈channel 没复用导致的消息排队现象是聚合报告里 p95 响应时间忽高忽低吞吐曲线上下波动大但 RabbitMQ 服务端 CPU 和内存都还正常。这个问题的根源在 channel 管理JMeter 线程每次发送都重新开 channel发送完关闭这个动作在低并发下很快但在高并发下 channel 的创建关闭变成了 broker 的瓶颈。解决方式是确认方案里每个连接上建立的 channel 被多次复用而不是一次一开同时可以把requestedHeartbeat调成 60 秒避免长时间空闲导致连接被服务端判定超时断开。这一项属于收益很高的参数微调值得在压测前就配好。5.4 消息发出去了但队列永远为空exchange 与 routing key 不匹配这个坑最隐蔽因为 JMeter 的 Sampler 会显示成功——publish 到 exchange 是成功了的但 exchange 找不到匹配的队列绑定消息被丢弃。检查消息是否真实入队的办法是看管理台的队列曲线如果压测期间 ready 数一直为 0 且没有消费者基本可以断定路由没对上。解决思路是核对 exchange 的类型和 binding keydirect 类型要求 routing key 完全匹配topic 类型要求通配符匹配fanout 类型忽略 routing key。把脚本里的 exchange 名称、routing key 与管理台绑定关系逐一对照排查大部分问题是大小写或多了前缀后缀。这个坑会直接让压测报告变成一张废纸务必在正式压测前用一小段消息做链路验证。5.5 压测机的 CPU 成了瓶颈JMeter 本身处理不过来高并发下压测结果曲线太平怎么加压吞吐都不涨但 RabbitMQ 服务端负载只有 30%。这时候问题大概率在压测机自身性能上JMeter 单机受限于 CPU 和内存尤其是当你用了大量 JSR223 脚本来做消息构造时。排查方式是观察压测机的 CPU 使用率如果压测机 CPU 已经接近 100% 而 broker 侧很闲就是压测机饱和了。解决思路是分布式压测或用更轻量的脚本逻辑表达式函数替代 JSR223不要把压力源本身变成瓶颈。这一点在方案落地时就要想清楚因为很多人会把压测机饱和误判为 broker 性能一般。6. 进阶用法用这套方案做稳定性测试和结果可视化验证压测跑通、数据能输出只是第一步真正值钱的用法是拿这套方案做稳定性和容量规划验证。场景是生产环境 RabbitMQ 集群上线前的验收需要验证新集群在持续高负载下运行 4 到 8 小时会不会出现内存水位上涨导致的消息堆积和未确认消息膨胀。做法是用命令行模式跑长时长场景把循环次数改成永远配合持续时间用-Jduration14400指定 4 小时脚本里把消息大小设定为贴近业务的规模线程数先用生产预估峰值的 70% 左右。跑的过程中每隔半小时用管理台的 API 拉一次队列深度和连接数曲线观察有没有周期性抖动。这个压测模式最怕跑一半没人盯所以要在命令行启动前把日志级别调低让 stdout 里的消息确认记录和错误流分开这样进程缓慢变差时你能第一时间从日志里发现端倪。结果可视化可以完全脱离 JMeter 的 HTML 报告把压测过程的采样数据推给具体的图表系统做实时展示但常用的就是 JMeter 自带的-e -o生成 HTML 报告里面有响应时间分布、吞吐量曲线和错误率三个核心面板。另一个用处是把结果 jtl 文件拿去做容量对比比如记录固定并发下不同消息大小对应吞吐量建立线性模型当新业务上线时用这个模型估算需要给 RabbitMQ 集群预留多少读写能力而不是凭感觉扩机器。用这套方案验证过三次集群上线之后我反而开始刻意不看单一数字——因为吞吐量只有在消息大小和确认模式都确定的场景下才有意义脱离了这些条件谈 TPS 都是空谈。希望帮到你如果在跑这套方案时遇到过更刁钻的报错回头再看管理台的明细曲线比看 JMeter 侧的堆栈更有用这是我再也不想犯的错误。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站