为什么需要分布式压测
JMeter是基于Java的应用,以线程的方式来模拟用户。每个线程占有的内存一般是8KB,所以并发用户较高时,使用单台计算机容易出现Java内存溢出错误。因而,在高并发时,通常需要借助多台机器同时发压,以产生足够的负载。
分布式压测的原理
-
控制节点(Master):控制节点是JMeter测试计划的中心节点,负责协调和控制整个压测过程。它从配置文件中读取Slave端地址,将测试计划分发到多个远程节点(Slave),收集并汇总测试结果。
-
远程节点(Slave):远程节点是测试计划的执行节点,负责实际模拟用户的并发访问行为。它们分布在多台物理机器上,可以是同一局域网中的多台机器,也可以是分布在不同地区的云主机。
-
测试计划同步:在开始压测之前,控制节点将测试计划分发到所有远程节点上,确保每个节点执行的测试计划是一致的。这些配置文件包括线程组配置、HTTP请求、断言、验证器等。
-
参数化文件:如果测试计划中用到了参数化文件,这些文件是不会被Master分发给Slave的,因为需要自己存放到Slave端。
-
并发执行:每个远程节点独立运行测试计划,并发地发送请求,并发数为测试计划中指定的并发数n。由于测试负载被分散到多个节点上执行,总并发数为节点数*n,可以实现高并发的访问效果。
-
结果收集:远程节点将测试结果发送回控制节点,控制节点负责收集、汇总和展示所有节点的结果。可以通过图形界面或者命令行查看压测结果,包括响应时间、吞吐量、错误率等。
分布式压测的简明步骤
前置条件
1、各个计算机在相同的目录下安装相同版本的JDK
2、各个计算机在相同的目录下安装相同版本的JMeter
3、各个JMeter的基础参数保持一致
配置
1、确定master(测试管理机)及slave(测试执行机)
2、Master配置
目录:%jmeter_home%/bin/
1)修改jmeter.properties:
指定slave的ip和端口(使用默认端口1099,如果不使用默认端口,在IP后面添加:端口号),如需添加slave节点,在此追加IP
remote_hosts=XX.XX.XX.1,XX.XX.XX.2
这里也可以不配置,执行时使用-R参数来指定slave机器:
jmeter.sh -n -t 脚本.jmx -R slaveIP1,slaveIP2
禁用ssl
server.rmi.ssl.disable=true
默认远程传输是需要加密的,如不禁用ssl,需要生成密钥及证书后进行配置。
2)修改jmeter-server:(IP为本机外网IP)
RMI_HOST_DEF=-Djava.rmi.server.hostname=XX.XX.XX.1
3)修改system.properties,指定hostname(IP为本机外网IP)
java.rmi.server.hostname=XX.XX.XX.1
3、slave配置
如需添加slave节点,复制本条操作,修改IP。IP为本机外网IP
目录:%jmeter_home%/bin/
1)修改jmeter.properties:
remote_hosts=XX.XX.XX.2
禁用ssl
server.rmi.ssl.disable=true
2)修改jmeter-server:
RMI_HOST_DEF=-Djava.rmi.server.hostname=XX.XX.XX.2
3)修改system.properties,指定hostname
java.rmi.server.hostname=XX.XX.XX.2
执行前的准备
1、修改脚本中的并发数
若需要压测100,在2台机器上执行,则线程设置50即可,jmeter执行中不会自动负载均衡,每一台服务器都会完整地运行测试计划。
2、脚本jmx文件
如常放置到master机器的脚本目录下。
注:Master和Slave最好分开。因为Master需要发送信息给Slave,并且接收从Slave传回的测试数据,会有一定的消耗,同时作为Slave发压机的话,可能导致Master性能不够。
3、数据文件
如有任何参数化文件,放置到所有slave机器上。
注:如果数据文件路径为相对路径,且原本指定为与脚本文件同一目录,则需要放置到%jmeter_home%/bin/目录下。分布式执行时,运行时当前目录为bin目录,而不是jmx脚本文件的目录。(为方便管理,可将所有的数据文件放置在一个文件夹下,如指定为./data/usrForLoan10.txt,则在bin下创建data文件夹统一放置数据文件)
如需要读取不同的数据(如登录账号互踢,不同server上需要使用不同的数据文件,可使用相同的文件名,但是内容不同即可。)
执行
1、启动jmeter-server
在所有要执行脚本的机器上启动jmeter-server(如master也需要作为发压机使用,也需要启动)
目录:%jmeter_home%/bin/
执行:nohup ./jmeter-server &
注:每次执行测试前,都需要杀死原本的jmeter-server进程并重新启动。否则执行脚本时会提示busy。
2、在master上启动测试脚本
目录:%jmeter_home%/bin/test-script
执行:nohup ../jmeter.sh -n -t 脚本.jmx -r -l 结果文件.jtl &
注:比原来的命令多了-r参数
3、启动后查看是否执行成功
1)查看各slave上的日志文件 %jmeter_home%/bin/jmeter-server.log,确保log在更新(原本写入test-script下面jmeter.log中的内容会被写入该文件。)
2)查看master上的jtl结果文件:确保请求分别被分发到不同的slave上
结果处理
1、处理jtl文件
将jtl文件导入jmeter时,为了使不同slave上的结果合并汇总,需要将jtl文件中slave IP删除,使用以下命令:
sed 's/XX\.XXX\.XX\.2-//g' 结果文件.jtl | sed 's/XX\.XXX\.XX\.1-//g'>removeIP.jtl
用空字符串替换目标字符串,其中,
- s表示替换;
- //中间的内容表示要被替换的字符串,"."是正则表达式中的特殊字符,需要使用"\"转义;
- 如果有要替换的字符,写在第二个/后面,比如's/stringToBeReplaced/newString/g'
- g表示行内全局查找
- 蓝色字体分别是待处理文件和最后生成的结果文件
2、将处理后的jtl文件导入jmeter
遗留问题
查看结果树中通常需要查看error msg,但是似乎只有执行脚本的master下面生成了error.jtl,仅有这一台机器的数据。slave机器上的错误信息未被记录。且jtl文件中的response msg为空,导致无法看到出错详情。