4. 性能测试工具:JMeter分布式压测环境搭建与脚本设计

说到性能测试,JMeter 绝对是绕不开的工具。我最早接触它的时候,还在用单机压测,结果被测服务没挂,我自己的电脑先卡死了。后来才明白——单机有瓶颈,分布式才是王道。

这一章,我就把分布式压测环境怎么搭、脚本怎么写,掰开了讲清楚。

4.1 为什么需要分布式压测?

你想想看,一台普通笔记本能发多少并发?撑死了几百到一千。要是被测接口要求 5000 并发,单机根本扛不住。原因有三:

  • 网络带宽限制:出口带宽就那么多,发出去的请求还没到服务器,自己先堵死了。
  • CPU/内存瓶颈:JMeter 本身也是 Java 进程,大量线程会吃掉本地资源。
  • 线程调度开销:单机线程数一高,上下文切换就把性能吃光了。

核心思路:用多台机器分担压力,一台当「控制器」,多台当「执行器」。控制器发号施令,执行器真正开枪。

4.2 分布式架构长什么样?

我习惯把分布式压测环境画成下面这张图,一看就明白:

JMeter 分布式压测架构图 Controller(控制器) 调度脚本 · 汇总结果 Agent 1(执行器) 发送请求 Agent 2(执行器) 发送请求 Agent N(执行器) 发送请求 目标服务器(Target Server) 被压测系统 说明:Controller 只负责调度和汇总,不参与实际请求发送,避免自身成为瓶颈

4.3 环境搭建:一步步来

搭建过程其实不复杂,但有几个坑。我踩过,所以给你列清楚。

4.3.1 准备工作

角色 机器要求 数量
Controller 4核8G以上,Windows/Linux均可 1台
Agent 2核4G以上,Linux优先 2~N台(视并发量而定)

所有机器必须安装相同版本的 JDK 和 JMeter。版本不一致?嗯,我遇到过,结果 Agent 连不上 Controller,排查了半天。

4.3.2 配置步骤

  1. Agent 端配置:找到 jmeter.properties,修改 server.rmi.ssl.disable=true(关闭 SSL,内网环境够用)。然后启动 jmeter-server 脚本。
  2. Controller 端配置:同样修改 jmeter.properties,添加 remote_hosts=Agent1_IP:1099,Agent2_IP:1099。
  3. 防火墙放行:Agent 的 1099 端口和随机 RMI 端口要开放。我习惯把 Agent 的 RMI 端口固定一下:
# 在 jmeter.properties 中设置
server.rmi.localport=50000
client.rmi.localport=50000

注意:Agent 和 Controller 之间网络要互通。我曾经在云环境里搭,安全组规则没配好,结果 Agent 一直报连接超时。白忙活两小时。

4.3.3 启动与验证

先启动所有 Agent,再启动 Controller 的 JMeter GUI。在「运行」菜单里选择「远程启动所有」,如果看到 Agent 开始接收任务,就说明环境通了。

4.4 脚本设计:分布式场景下的要点

脚本设计和单机差不多,但有几个地方要特别注意。

4.4.1 参数化与数据隔离

每个 Agent 都要用不同的测试数据,否则会出现重复登录、重复下单的问题。我常用的方案:

  • CSV 数据文件:每个 Agent 分配不同的 CSV 文件,或者用 __threadNum 函数做偏移。
  • 唯一 ID 生成:用 ${__UUID} 或者时间戳+线程号组合。
// 示例:生成唯一订单号
${__time(yyyyMMddHHmmss)}_${__threadNum}_${__counter(TRUE)}

4.4.2 断言与监听器

分布式压测时,不要在每个 Agent 上都加图形监听器。图形监听器(比如聚合报告、结果树)会消耗大量内存,导致 Agent 性能下降。

我的做法:

  • Agent 只加 简单数据写入器,把结果写到本地 CSV。
  • Controller 汇总后,再用 聚合报告 分析。

小技巧:如果非要实时看数据,可以用 Backend Listener 把结果推送到 InfluxDB,然后用 Grafana 展示。这样 Agent 零负担,数据还直观。

4.4.3 线程组设计

假设总目标并发是 2000,你有 4 台 Agent。每台 Agent 的线程数设为 500 就行。注意:不要用「总线程数/Agent 数」自动计算,手动分配更可控。

总并发目标 Agent 数量 每 Agent 线程数
1000 2 500
2000 4 500
5000 10 500

4.5 常见问题与避坑

  • Agent 连不上 Controller:先 ping,再 telnet 端口。八成是防火墙或 RMI 端口没固定。
  • 结果汇总不一致:检查所有机器的 JMeter 版本,必须一致。我吃过这个亏,版本差一个小版本,结果数据对不上。
  • Agent 内存溢出:修改 jmeter 启动脚本的 HEAP 参数,比如 HEAP="-Xms2g -Xmx4g"。
  • 网络延迟导致结果偏差:Agent 尽量和被测服务部署在同一网段,跨机房压测要评估网络开销。

一句话总结:分布式压测的核心是「控制与执行分离」。环境搭好只是第一步,脚本设计和数据隔离才是真正考验功力的地方。