说明
jmeter 分布式压测:将需要模拟的大量并发用户数分发到多台压力机,使 jmeter 拥有更大的负载量,满足真实业务场景(高并发场景)。 一台压力机(用来跑脚本的电脑)的 jmeter 默认最大支持 1000 左右的并发用户数(线程数),再大的话,容易造成卡顿、无响应等情况,这是受限于 jmeter 其本身的机制和硬件配置(内存、CPU等); 由于 jmeter 是 java 应用,对 CPU 和内存的消耗较大,在需要模拟大量并发用户数时,单机很容易出现 java 内存溢出,导致测试脚本本身就有瓶颈。 场景: 测试 5000 并发的场景,如果只用一台电脑跑压测脚本,无法达到 5000 并发(因为单机只能支持1000并发)。此时就需要通过分布式模拟5000并发(5台机器起)。 通过一个 Jmeter 控制台来远程控制多个 Jmeter 引擎完成测试。
Apache Jmeter 官网地址:https://jmeter.apache.org/
Apache Jmeter 下载地址:https://jmeter.apache.org/download_jmeter.cgi
Apache Jmeter 分布式压测官方文档:https://jmeter.apache.org/usermanual/jmeter_distributed_testing_step_by_step.html
Apache Jmeter 插件库:https://jmeter-plugins.org/
原理
jmeter 分布式原理:由控制机发压测脚本到每台远程执行机(压力机),然后由控制机收集执行机结果。 注意:控制机主要用于控制整个压测机器集群并收集执行数据,汇总结果。控制机也可以当做压力机。 压力机系统类型无限制:win、mac、linux 都可以。
Jmeter 分布式压测架构图
本文采用一台控制机,三台压力机进行实验。
压测环境搭建
集群环境
四台机器的相关配置如下表。
机器 | 环境 | IP 地址 | 端口(server_port) |
---|---|---|---|
控制机 | Windows 10 | 192.168.56.1 | 10950 |
压力机01 | CentOS 8 | 192.168.56.21 | 10955 |
压力机02 | CentOS 8 | 192.168.56.22 | 10955 |
压力机03 | CentOS 8 | 192.168.56.23 | 10955 |
软件环境
JDK:Java 8(理论上,大版本一致即可) Apache Jmeter:5.5 将 Apache Jmeter 上传到压力机上,并解压到 /usr/local/jmeter 目录中。
[root@localhost tmp]# mkdir /usr/local/jmeter
[root@localhost tmp]# unzip apache-jmeter-5.5.zip -d /usr/local/jmeter/
目标服务
创建一个 web 服务作为压测的目标服务。
编写服务
此处采用 nodejs 编写一个简单的服务。 创建 web-api.js 文件,内部代码如下:
var http = require('http');
var times = 0;
const server = http.createServer(function (req, res) {
res.end("HelloWorld - " + Date.now());
console.log("请求来自" + req.connection.remoteAddress + ",当前请求次数: " + times++);
})
server.listen(12345);
console.log('Server running at port: 12345 ...');
启动服务
需要安装 node 环境。 进入该文件所在目录,执行下面的命令,启动服务。
node web-api.js
服务启动成功后,会监听 12345 端口。 使用浏览器,访问服务所在主机的该端口,就可以请求服务了。 该服务所在主机 IP 为:192.168.56.1,因此可以请求:http://192.168.56.1:12345。
访问成功,结果图上图所示。
此处访问两次的原因是,浏览器默认会请求一次 favicon.ico。
Apache Jmeter 配置
压力机配置(以压力机01为例)
压力机主要是 Linux 系统。
hostname
确保 hostname 不是 localhost.localdomain。 查看 hostname
[root@localhost bin]# hostname
localhost.localdomain
修改 hostname 为 machine01,重启计算机生效。
hostnamectl set-hostname machine01
修改 /etc/hosts,将 machine01 指向本机的 IP 地址,该地址不能是回环地址(127.0.0.1)。
vim /etc/hosts
jmeter.properties
修改服务监听的端口,关闭 SSL 认证。
server_port=10955
server.rmi.ssl.disable=true
其他的压力机配置方法与当前机器的配置类似,具体参数根据实际情况配置。
系统参数调整
linux系统参数优化。linux默认最大连接数1024,在压测过程中经常会出现连接数不足导致的异常,需要先调整系统参数再做测试。 修改 /etc/sysctl.conf 配置文件
vm.max_map_count=655360
vm.swappiness=1
fs.file-max=655356000
fs.nr_open=104857600
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
让 sysctl 配置生效
sysctl -p
修改 /etc/security/limits.conf
root soft nofile 1048576
root hard nofile 67108864
root soft nproc 102400
root hard nproc 655360
* soft memlock unlimited
* hard memlock unlimited
启动压力机服务
在 jmeter 安装目录中的 bin 目录下,启动 jmeter-server 服务。
[root@machine01 bin]# ./jmeter-server
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[192.168.56.21:32971](local),objID:[-3568d989:184ef374e05:-7fff, 7836004259729148648]]]
控制机配置
控制机为 Windows 系统。
jmeter.properties
配置控制机的远程控制地址和端口,关闭 SSL 认证。
remote_hosts=192.168.56.21:10955,192.168.56.22:10955,192.168.56.23:10955
server_port=10950
server.rmi.ssl.disable=true
压力测试
启动控制机 jmeter 界面
在控制机的 jmeter 目录下的 bin 目录中,启动 jmeter 应用程序。
jmeter.bat
jmeter 启动后,界面如下图所示。
添加一个压测计划,使用 10 个线程(用户),发送 HTTP 请求。
定义 HTTP 采样器,并配置要访问的服务器地址,端口等信息。
再添加结果树、聚合报告,用于查看压测结果。
检查压力机服务是否运行正常
点击控制机上面菜单中的 Run,选择 Remote Start,分别测试每一台压力机是否运行正常。 在这个过程中,可以先将线程组配置小一点。
分别测试各个压力机,在目标服务器控制台上,看到下面的结果,表示压力机运行正常。
启动分布式压测
jmeter 的运行方式有两种模式:GUI 模式、CLI 模式。因此分布式压测有就有两种方式。
GUI 模式
启动控制机的 jmeter 的安装目录下的 bin 目录中的 jmeter.bat,启动 jmeter 界面。 此时,可以修改好线程组的数量,在控制机中配置的线程数以及运行次数等信息,会分发给所有的压测机执行,即:每台压测机都会执行该配置下的压测。 配置好线程组信息后,启动所有压力机。 点击控制机上面菜单中的 Run,选择 Remote Start All,即同时启动所有压力机。
远程压力机接收指令并执行成功的话,会看到 Starting ... 和 Finished ... 两行信息。
[root@machine01 bin]# ./jmeter-server
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[192.168.56.21:32971](local),objID:[-3568d989:184ef374e05:-7fff, 7836004259729148648]]]
Starting the test on host 192.168.56.21:10955 @ December 8, 2022 8:52:42 AM CST (1670460762930)
Finished the test on host 192.168.56.21:10955 @ December 8, 2022 8:52:44 AM CST (1670460764297)
在压测的过程中,可以在聚合报告中,看到压测的结果。 此处配置的线程组中的线程数是 10,循环一次,共有 3 台压力机,因此采样数量就是 10*3=30,总共执行了 30 次请求。
分布式压测完成。
CLI 模式
控制机进入 jmeter 的安装目录下的 bin 目录中,打开控制台。
# 执行压测脚本,-r 表示启动所有压力机;-R:IP:PORT 启动指定压力机
jmeter -n -t ${jmx_file_path} -r -l ${jtl_result_path}
# 生成报告
jmeter -g ${jtl_result_path} -e -o ${output_dir_path}
说明
{jtl_result_path}:jtl 结果存储位置;
${output_dir_path}:测试报告的结果保存目录;
案例
# 指定压力机执行压测脚本
jmeter -n -t /home/test/test.jmx -R 192.168.56.21:10955,192.168.56.22:10955 -l /home/test/test_result.jtl
# 创建目录
mkdir -p /home/test/results
# 生成报告
jmeter -g /home/test/test_result.jtl -e -o /home/test/results
常见问题
在进行分布式压测的过程中,可能会遇到一些问题。
loopback address 问题
[root@localhost bin]# ./jmeter-server
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[127.0.0.1:46787](local),objID:[-4b9cf262:184ed155baf:-7fff, -7793164881645611591]]]
Server failed to start: java.rmi.RemoteException: Cannot start. localhost.localdomain is a loopback address.
An error occurred: Cannot start. localhost.localdomain is a loopback address.
解决方法
方法一
修改 hostname,让主机名指向本机非回环地址。 例如:压力机01 的 IP 地址为 192.168.56.21,修改 hostname 为 machine01,重启计算机生效。
hostnamectl set-hostname machine01
修改 /etc/hosts,将 machine01 指向本机的 IP 地址,该地址不能是回环地址(127.0.0.1)。
vim /etc/hosts
方法二
带本地IP参数启动 jmeter-server
# windows
jmeter-server.bat -Djava.rmi.server.hostname=192.168.56.21
# Linux
./jmeter-server -Djava.rmi.server.hostname=192.168.56.21
方法三
修改 jmeter-server,固定压力机的 RMI_HOST_DEF。
RMI_HOST_DEF=-Djava.rmi.server.hostname=192.168.56.21
然后启动 jmeter-server 服务。
SSLHandshakeException
error during JRMP connection establishment; nested exception is:
javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake
解决方法
修改 jmeter.properties,关闭 SSL 认证。
server.rmi.ssl.disable=true
RegCreateKeyEx(...)
WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
解决方法
使用管理员权限启动 jmeter-server.bat。
rmi_keystore.jdk
解决方法
出现该问题的原因是,压力机需要控制机提供认证文件。
方法一
修改 jmeter.properties 配置文件,关闭 SSL 认证。
server.rmi.ssl.disable=true
方法二
启动 create-rmi-keystore.bat,生成一个认证文件。
将该文件分发到所有压力机的 jmeter 安装目录中的 bin 目录下。 重启压力机 jmeter-server 服务。
机器之间 PING 不通
所有的机器最好在同一个局域网,关闭防火墙。 windows 关闭防火墙。
Linux 关闭防火墙
systemctl stop firewalld
远程服务执行脚本后,响应数据为空
jmeter 客户端默认是统计模式,不显示响应数据,减少开销。 如果想要查看响应数据,修改 jmeter.properties 配置文件。
mode=Standard