##分布式配置##
为什么要做分布式
Jmeter 本身的局限性
- 一台压力机的 Jmeter 默认最大支持 1000 左右的并发用户数(线程数),再大的话,容易造成卡顿、无响应等情况,这是受限于 Jmeter 其本身的机制和硬件配置(内存、CPU等)
- 由于 Jmeter 是 Java 应用,对 CPU 和内存的消耗较大,在需要模拟大量并发用户数时,单机很容易出现 JAVA 内存溢出的错误,导致测试脚本本身就有瓶颈
JVM 堆内存的局限性
Java 应用的 jvm 堆内存 heap 受压力机硬件限制,虽然我们可以调整堆内存大小
cmd 启用 Jmeter GUI 时,也会有提示
increase Java Heap to meet your test requirements: Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
翻译:增加 Java 堆内存来满足测试的要求
但是单机无法支撑数以万计大并发,此时,需要多个压力机进行分布式压力测试,这样性能瓶颈就不会是我们的压力机了
联想场景
- 测试 5000 并发的场景,但单机只能支持 1000 并发无法达到 5000
- 通过分布式(5 台机器起)可以模拟 5000 并发
分布式压测
Jmeter 支持分布式压测,将需要模拟的大量并发用户数分发到多台压力机,使 Jmeter 拥有更大的负载量,满足真实业务场景(高并发场景)
分布式的最终目的
- 确保压力机不会出现性能瓶颈
- 在后面进行性能分析时,不需要考虑压力机是否会导致性能瓶颈的主要原因之一
分布式原理
把上面的动图完整看完,就懂了,原理如下:
- Master 是控制机,Slaves 是多个压力机,Target 是被测系统
- 分布式测试中,Master 通过命令行将测试脚本分发给所有 Slave
- Slave 不需要启动 Jmeter GUI,通过 CLI 模式执行测试
- Slave 执行完后,会把结果回传给 Master
- Master 收集所有 Slave 的结果并汇总成一个结果集
注意
-
压力机也可以叫:负载机、代理机、执行机、奴隶机、肉鸡....各种各样的名字,但他们都是 Slave
-
Master 也可以****执行测试脚本,也可以不执行只负责管
分布式专用术语认知
Master
- 控制机
- 运行JMeter GUI(控制测试)的机器
Slave
- 压力机
- 运行 jmeter-server 的机器
- 它从 GUI 接收命令并将请求发送到目标系统
target
需要进行压力测试的 Web 服务器
实现分布式的前提条件
控制机和压力机的 jmeter 要一致
具体体现在
- jmeter 版本要一致
- jdk 主版本要一致(1.7、1.8...)
- jmeter 脚本中,csv 文件要一致
- jmeter 的插件要一致
- 同一局域网,防火墙开放端口
jdk 版本一致
看主版本即可
csv 文件一致
主要是数据和路径要一致
如何保持一致可以参考这篇博客:https://www.cnblogs.com/blog-123/p/15189379.html
保证一致性方法
直接将控制机的 jmeter 压缩包移到每个压力机上解压使用
压力机配置
注意:压力机系统不限,可以是win、mac、linux
前置步骤
将控制机的 jmeter 压缩包发送到压力机,解压
(如果你服务器禁止传送的话,那就wget + 官方包路径也可以的哦)
修改 jmeter.properties(下面三步走)
进入 bin 目录
修改 server_port 端口
默认1099
可修改任意端口,但不能已被占用的哦
修改 server.rmi.port 端口
和 server_port 保持一致即可, 默认是会帮你保持一致的
设置 server.rmi.ssl.disable
默认 false,代表需要认证
设置为 true,减少不必要的麻烦
启动 jmeter-server 服务
仍然在 bin 目录下哦
如果压力机是 linux 或 mac
./jmeter-server -Djava.rmi.server.hostname=压力机ip
# 提示:
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
At least one of these environment variable is needed to run this program
请安装jdk 看这个文章https://www.cnblogs.com/blog-123/p/15343502.html
如果是window
jmeter-server.bat -Djava.rmi.server.hostname=压力机ip
检查防火墙
- 检查防火墙是否被关闭,防火墙会影响脚本执行和测试结构收集
- 确认 server_port 的端口没有被占用以及需要对外开放,端口占用会导致压力机报错
控制机配置
修改 jmeter.properties(下面三步走)
修改 remote_hosts
- 多个压力机之间用 , 隔开
- 不同压力机端口可以不一样,不需要全部都一致
- 如果控制机也测试则加 127.0.0.1:port ,然后修改 server_port 和 server.rmi.port (和压力机一样步骤)
设置 server.rmi.ssl.disable
设置 mode
- 用于查看分布式测试过程中,每个压力机的测试结果
- 若不启用,在运行过程中,控制器是无法实时看到压力机的结果
控制机运行分布式测试
启动远程服务器
这里会显示所有 remote_hosts 添加的压力机
点击启动后,查看压力机
分布式注意事项
- 如果并发较高,建议将控制机设置为只启动测试脚本和收集汇总测试结果
- 分布式测试中,如果 1S 发送 100 个模拟请求,有 5 个压力机,那么需要将脚本的线程数设置为 20,否则模拟请求数会变成 500,和预期结果相差太大
- 只需要修改控制机的脚本,启动压力机之后,压力机执行的就是最新的脚本
如果你说你看不懂那你就按这个步骤 脑瓜似的操作吧
点击查看代码
# 从一而终的步骤:
1、在master和slaves机器上分别按照相同版本的jdk和jmeter
2、在master机器上
1)修改配置文件,进入jmeter/bin目录下
vim jmeter.properties
remote_hosts=192.168.0.102:8899,192.168.0.101:8899(slaves机器的ip和端口)
server.rmi.ssl.disable=true(禁用ssl)
如果master即作为master也作为slaves
remote_hosts=192.168.0.102:8899,192.168.0.101:8899,master的ip:8899
server_port=8899
server.rmi.ssl.disable=true(禁用ssl)
2)启动jmeter服务
./jmeter-server(linux)
jmeter-server.bat(windows)
3)检查是否启动成功
ps -ef|grep jmeter-server
3、在slaves机器上
1)修改配置文件,进入jmeter/bin目录下
vim jmeter.properties
remote_hosts=127.0.0.1
server_port=8899
server.rmi.ssl.disable=true(禁用ssl)
2)启动jmeter服务
./jmeter-server(linux)
jmeter-server.bat(windows)
3)检查是否启动成功
ps -ef|grep jmeter-server
4、分布式执行
GUI模式 :运行——》远程启动、远程启动全部
non-GUO模式:命令行增加-r参数
jmeter -n -t /Users/jack/Desktop/remote.jmx -r -l /Users/jack/Desktop/jtl/result.jtl -e -o /Users/jack/Desktop/result
四、常见问题
安装常见问题
1、问题
[root@iZwz95j86y235aroi85ht0Z bin]# ./jmeter-server
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[:39308](local),objID:[24e78a63:16243c70661:-7fff, 7492480871343944173]]]
Server failed to start: java.rmi.RemoteException: Cannot start. Unable to get local host IP address.; nested exception is:
java.net.UnknownHostException: iZwz95j86y235aroi85ht0Z: iZwz95j86y235aroi85ht0Z: Name or service not known
An error occurred: Cannot start. Unable to get local host IP address.; nested exception is:
java.net.UnknownHostException: iZwz95j86y235aroi85ht0Z: iZwz95j86y235aroi85ht0Z: Name or service not known
解决:
hostname 命令获取机器名称,追加一个映射 iZwz95j86y235aroi85ht0Z
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
120.79.160.143 iZwz95j86y235aroi85ht0Z
windows用户 修改c:\windows\system32\drivers\etc\hosts文件,增加一条域名 与IP的映射
2、问题
[root@iZwz95j86y235aroi85ht0Z bin]# ./jmeter-server
Server failed to start: java.rmi.server.ExportException: Listen failed on port: 0; nested exception is:
java.io.FileNotFoundException: rmi_keystore.jks (No such file or directory)
An error occurred: Listen failed on port: 0; nested exception is:
java.io.FileNotFoundException: rmi_keystore.jks (No such file or directory)
解决:
拥有RMI over SSL的有效密钥库,或者禁用了SSL。
1、禁用SSL
jmeter.property里面 server.rmi.ssl.disable 改为 true,表示禁用
3、问题:
[root@userCenter bin]# ./jmeter-server
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[127.0.0.1:39687](local),objID:[-18db419a:167773db861:-7fff, -176377700206527642]]]
Server failed to start: java.rmi.RemoteException: Cannot start. userCenter is a loopback address.
An error occurred: Cannot start. userCenter is a loopback address.
解决:
执行时加上参数./jmeter-server -Djava.rmi.server.hostname=10.1.1.222
4、问题:
[root@iZ949uw2xehZ bin]# ./jmeter
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c0000000, 1073741824, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 1073741824 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /usr/local/jmeter/apache-jmeter-4.0/bin/hs_err_pid5855.log
解决:
编辑jmeter
搜索 : "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"
改变初始堆内存和最大堆内存
5、仅修改 server_port 即可,下面两者一样
server.rmi.localport=8899 表示slave server启动显示的端口
server_port=8899 表示master机器要远程连接的端口 即 remote_hosts=xxxx:8899
6、<!-- jmeter 分布式性能测试(多网卡配置) -->
我们要在多网卡的服务器上开启RMI服务的话必须指定IP,使他们能够在同一个网段内。
需要以下几步(假定所有机器都在10.120.11.*网段,agent服务器为linux,controller服务器为windows):
1) 修改agent服务器,指定agent机器的IP
修改jmeter-server文件
# vi jmeter-server
修改RMI_HOST_DEF=-Djava.rmi.server.hostname=xxx.xxx.xxx.xxx(需要连接的IP)
2)修改server服务器,指定server机器的IP
修改jmeter.bat文件
新增set rmi_host=-Djava.rmi.server.hostname=10.120.11.214
修改set ARGS=%DUMP% %HEAP% %NEW% %SURVIVOR% %TENURING% %PERM% %DDRAW% %rmi_host%
7、确定在controller机器上安装jdk,版本和jmeter一致,配置环境变量:Java_home等
在Agent机器上安装jdk,配置环境变量:Java_home和JMeter_home
安装目录不要带空格,最好都是简短的英文路径
8、master机器启动后会拷贝jmx文件到slave机器,所以不需要在每台slave机器上也上传一份jmx,只需要在master机器上上传一份jmx脚本即可。
如果使用csv进行参数化,则需要把参数文件在每台slave上拷一份且路径需要设置成一样的。
总样本数 = 线程数 * 循环次数 * 执行机总数
9、连接失败原因排查
以下步骤进行排查:
1. jmeter-server是否启动;
2. 是否联网
3. ping 服务器IP是否畅通.
4. telnet 端口 192.168.3.10 1099
5. 检查服务器的防火墙是否关闭。
6. 阿里云安全策略是否正常
10、"could not find ApacheJmeter_core.jar"
解决:在Agent机器安装jdk,并设置环境变量
11、”Bad call to remote host"
解决:检查被控制机器上的jmeter-server有没有启动,或者remote_hosts的配置是否正确。