jmeter
gui
0、下载 jmeter 及 jdk-8,
1、设置 java 环境变量
控制面板>系统安全>系统>高级系统设置>环境变量>系统变量
Path
增加java的目录 \bin2、添加线程组:右键点击“测试计划” -> “添加” -> “Threads(Users)” -> “线程组”
线程组参数详解:
1. 线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里也就是设置多少个线程数。
2. Ramp-Up Period(in seconds)准备时长:设置的虚拟用户数需要多长时间全部启动。如果线程数为10,准备时长为2,那么需要2秒钟启动10个线程,也就是每秒钟启动5个线程。
3. 循环次数:每个线程发送请求的次数。如果线程数为10,循环次数为100,那么每个线程发送100次请求。总请求数为10*100=1000 。如果勾选了“永远”,那么所有线程会一直发送请求,一到选择停止运行脚本。
4. Delay Thread creation until needed:直到需要时延迟线程的创建。
5. 调度器:设置线程组启动的开始时间和结束时间(配置调度器时,需要勾选循环次数为永远)
持续时间(秒):测试持续时间,会覆盖结束时间
启动延迟(秒):测试延迟启动时间,会覆盖启动时间
启动时间:测试启动时间,启动延迟会覆盖它。当启动时间已过,手动只需测试时当前时间也会覆盖它。
结束时间:测试结束时间,持续时间会覆盖它。3、添加 HTTP 请求:右键点击“线程组” -> “添加” -> “Sampler” -> “HTTP 请求”
Web服务器
协议:向目标服务器发送HTTP请求协议,可以是HTTP或HTTPS,默认为HTTP
服务器名称或IP :HTTP请求发送的目标服务器名称或IP
端口号:目标服务器的端口号,默认值为80
2.Http请求
方法:发送HTTP请求的方法,可用方法包括GET、POST、HEAD、PUT、OPTIONS、TRACE、DELETE等。
路径:目标URL路径(URL中去掉服务器地址、端口及参数后剩余部分)
Content encoding :编码方式,默认为ISO-8859-1编码,这里配置为utf-8
同请求一起发送参数
在请求中发送的URL参数,用户可以将URL中所有参数设置在本表中,表中每行为一个参数(对应URL中的 name=value),注意参数传入中文时需要勾选“编码”4、添加察看结果树:右键点击“线程组” -> “添加” -> “监听器” -> “察看结果树”
5、添加聚合报告:右键点击“线程组” -> “添加” -> “监听器” -> “聚合报告”,用以存放性能测试报告
聚合报告参数详解:
1. Label:每个 JMeter 的 element(例如 HTTP Request)都有一个 Name 属性,这里显示的就是 Name 属性的值
2. #Samples:请求数——表示这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100
3. Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,以Transaction 为单位显示平均响应时间
4. Median:中位数,也就是 50% 用户的响应时间
5. 90% Line:90% 用户的响应时间
6. Min:最小响应时间
7. Max:最大响应时间
8. Error%:错误率——错误请求数/请求总数
9. Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数
10. KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec
一般而言,性能测试中我们需要重点关注的数据有: #Samples 请求数,Average 平均响应时间,Min 最小响应时间,Max 最大响应时间,Error% 错误率及Throughput 吞吐量。Java 系统属性和 JMeter 属性可以直接通过以下命令进行覆盖,而不用手动修改 jmeter.properties
| 格式 | 含义 |
|---|---|
| -J[prop_name]=[value] | 定义本地 JMeter 属性 |
docker
拉取镜像
docker pull justb4/jmeter
docker run --rm \
-v /root/jmeter:/opt/jmeter \
-e JVM_ARGS="-Xms512m -Xmx2g" \
justb4/jmeter \
-n -t /opt/jmeter/shuze_template.jmx \
-Jprotocol=https \
-Jdomain=shuze.net \
-Jport=443 \
-Jmethod=GET \
-Jpath=/api/CommonService/common/sample \
-Jthreads=10 \
-Jrampup=1 \
-Jduration=60 \
-l /opt/jmet/test.jtl自己构建
# jmeter.dockerfile
FROM openjdk:8-jdk-alpine
ARG JMETER_VERSION=5.6.3
ARG ALIYUN_MIRROR=https://mirrors.aliyun.com/apache/jmeter
WORKDIR /jmeter
# 下载并安装 JMeter
# RUN wget ${ALIYUN_MIRROR}/binaries/apache-jmeter-${JMETER_VERSION}.tgz && \
# tar -xzf apache-jmeter-${JMETER_VERSION}.tgz --strip-components=1 && \
# rm apache-jmeter-${JMETER_VERSION}.tgz
#已下载
RUN tar -xzf apache-jmeter-${JMETER_VERSION}.tgz --strip-components=1 ;
# 设置环境变量
ENV JMETER_HOME /jmeter
ENV PATH $JMETER_HOME/bin:$PATH
EXPOSE 1099
WORKDIR /tests
ENTRYPOINT ["jmeter"]docker build -t jmeter:5.6.3 . -f jmeter.dockerfile
docker run --rm \
-v /root/jmeter:/opt/jmeter \
-e JVM_ARGS="-Xms512m -Xmx2g" --name jmeter \
registry.cn-shenzhen.aliyuncs.com/shuze/jmeter:5.6.3 \
-n -t /opt/jmeter/shuze_template.jmx \
-Jprotocol=https \
-Jdomain=shuze.net \
-Jport=443 \
-Jmethod=GET \
-Jpath=/api/CommonService/common/sample \
-Jthreads=10 \
-Jrampup=1 \
-Jduration=60 \
-l /opt/jmet/test.jtlcli
jmeter -n -t sample.jmx -l result.out -e -o /opt/jmeter/report
docker run --rm \
-v /root/jmeter:/opt/jmeter \
-e JVM_ARGS="-Xms512m -Xmx2g" \
justb4/jmeter \
-n -t /opt/jmeter/shuze_template.jmx \
-Jprotocol=https \
-Jdomain=shuze.net \
-Jport=443 \
-Jmethod=GET \
-Jpath="/api/CommonService/ModelProp/ModelTableHeadersByName?moduleName=WaterSupervision&modelName=Section" \
-Jthreads=10 \
-Jrampup=1 \
-Jduration=60 \
-Jaccess_token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1QzlwTzVOTGQxR0JlZ0MzWnNnUWloYmpoQk85bHBMOE9CenRLbjByUFZNIn0.eyJleHAiOjE3NjE3Mjk1MTcsImlhdCI6MTc2MTcyNzcxNywiYXV0aF90aW1lIjoxNzYxNjE1ODI5LCJqdGkiOiJiNWU4ZmNiZi0wMTI0LTQ2MTUtOWI5Ny05OTBkODlmNzkwZTciLCJpc3MiOiJodHRwczovL3NodXplLm5ldC9rZXljbG9hay9yZWFsbXMvc2h1emUiLCJhdWQiOlsicmVhbG0tbWFuYWdlbWVudCIsImJyb2tlciIsImFjY291bnQiXSwic3ViIjoiMjExMzA5MzItZTAzNC00MzQ0LWI2OTItYzYyYmI1NDBlYTdmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiU2h1emVXZWIiLCJub25jZSI6ImVhZWM3NGY5LWE0Y2YtNDg3Ny04OTg0LWM1NDBmNDJhNzgzOCIsInNlc3Npb25fc3RhdGUiOiIyNDFlNDY4YS03OWRlLTQyNTktOTRiNy02YzE0NTM5YzU1ZDYiLCJhY3IiOiIwIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsInNpZCI6IjI0MWU0NjhhLTc5ZGUtNDI1OS05NGI3LTZjMTQ1MzljNTVkNiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicm9sZSI6WyJhZG1pbi1yb2xlIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsIumYsuW-oeWkhCIsIuawtOi1hOa6kOWkhCIsInVtYV9hdXRob3JpemF0aW9uIiwiZGVmYXVsdC1yb2xlcy1zaHV6ZSIsIuW7uueuoeWkhCJdLCJuYW1lIjoiYWRtaW4gbGkiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJhZG1pbiIsImZhbWlseV9uYW1lIjoibGkiLCJlbWFpbCI6ImFkbWluQHNodXplLm5ldCJ9.kUb46Wa5VvsOs0S2vRrSEE01k0D4zJqL1fK0Rp3NitYY3joyKwEwB1srN-fEC_ixb72ifoVcTUTPfcREhGeeMPcTs8TX8m-VY3C2MRiT8WhuaUY_OPBXpr6-2YluxnEyN6z3jyvWmJ1NCcXonLFA11c_MjjQgAgSiwE_ijhFYtOLj8o5XMP_r8kbqoHWiA1_igWOZX5HbfrfLxcahF8Wi-4O7CUf8Setvp2pUOLjUGApNez7cBNCDZtS7Esp_-Q74qRStX-nywe_v_j2EbAviIvwGDZdKVtVizTFOFOQBmUrPUMUNUpUJUFSgNevXsioxV2Db-kChiW5ty3e9Losdg \
-l /opt/jmet/test.jtl
docker run --rm \
-v /root/jmeter:/opt/jmeter \
-e JVM_ARGS="-Xms512m -Xmx2g" \
justb4/jmeter \
-n -t /opt/jmeter/shuze_template.jmx \
-Jprotocol=https \
-Jdomain=shuze.net \
-Jport=443 \
-Jmethod=GET \
-Jpath="/api/CommonService/ModelProp/RedisModelTableHeadersByName?moduleName=WaterSupervision&modelName=Section" \
-Jthreads=1 \
-Jrampup=1 \
-Jduration=60 \
-Jaccess_token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ1QzlwTzVOTGQxR0JlZ0MzWnNnUWloYmpoQk85bHBMOE9CenRLbjByUFZNIn0.eyJleHAiOjE3NjE3MDMyOTUsImlhdCI6MTc2MTcwMTQ5NSwiYXV0aF90aW1lIjoxNzYxNjE1ODI5LCJqdGkiOiIyOGI3Yzc2NC02YWJlLTQ0NGYtODZkYi1kNWYwNjczOGNiZTUiLCJpc3MiOiJodHRwczovL3NodXplLm5ldC9rZXljbG9hay9yZWFsbXMvc2h1emUiLCJhdWQiOlsicmVhbG0tbWFuYWdlbWVudCIsImJyb2tlciIsImFjY291bnQiXSwic3ViIjoiMjExMzA5MzItZTAzNC00MzQ0LWI2OTItYzYyYmI1NDBlYTdmIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiU2h1emVXZWIiLCJub25jZSI6IjBlZDMzM2JhLTg1YmUtNGY5Mi1iY2UwLTU3MzBiNWZjMjhhYyIsInNlc3Npb25fc3RhdGUiOiIyNDFlNDY4YS03OWRlLTQyNTktOTRiNy02YzE0NTM5YzU1ZDYiLCJhY3IiOiIwIiwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsInNpZCI6IjI0MWU0NjhhLTc5ZGUtNDI1OS05NGI3LTZjMTQ1MzljNTVkNiIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicm9sZSI6WyJhZG1pbi1yb2xlIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsIumYsuW-oeWkhCIsIuawtOi1hOa6kOWkhCIsInVtYV9hdXRob3JpemF0aW9uIiwiZGVmYXVsdC1yb2xlcy1zaHV6ZSIsIuW7uueuoeWkhCJdLCJuYW1lIjoiYWRtaW4gbGkiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiIsImdpdmVuX25hbWUiOiJhZG1pbiIsImZhbWlseV9uYW1lIjoibGkiLCJlbWFpbCI6ImFkbWluQHNodXplLm5ldCJ9.D2vaXiu5eK6UNv8HViYceI3O1h46jqaFC-ZwEh2uT1H-s25KXKNwL7dnfuJem0FP7srz6mNavxLbghmkhVlQLOA0Fbw5XVr_ZRTUQOfVEB2Fo95uXRETBd4O7UqW-Jo2aViZIHWMsn89zZZ9-X4dIcAfuPAD3EX9fK_pUg6O5tpOP0b0L-DmkVaQr8Wr7YsCflgPxBXkjUeNjE27kjjY_sKSOoDcvsMELvjzBZsbhpkTw-mSfCbOEPex4qEIKZZoIByaxmQ5Gta53Vd60NI_AaP8HirietwE7bubVaiJBcVOkkpKss1cQR9crb8wDOWjyp-cOX-3wnXC0Fzrfgk0uA \
-l /opt/jmet/test.jtl
curl -H "Authorization: Bearer YOUR_TOKEN" \
-w "总时间: %{time_total}s\nDNS解析: %{time_namelookup}s\n连接建立: %{time_connect}s\nTLS握手: %{time_appconnect}s\n请求发送: %{time_pretransfer}s\n等待响应: %{time_starttransfer}s\n" \
http://139.9.220.83:8002/api/WaterSupervision/Section/Table
curl -H "Authorization: Bearer YOUR_TOKEN" \
-w "总时间: %{time_total}s\nDNS解析: %{time_namelookup}s\n连接建立: %{time_connect}s\nTLS握手: %{time_appconnect}s\n请求发送: %{time_pretransfer}s\n等待响应: %{time_starttransfer}s\n" \
https://shuze.net/api/WaterSupervision/Section/Table${__P(threads,10)}
${__P(rampup,1)}
${__P(duration,60)}
${__P(protocol,https)}
${__P(domain,shuze.net)}
${__P(port,443)}
${__P(method,GET)}
${__P(path,/api/CommonService/common/sample)}
${__P(results_dir,)}/aggregate.csv# 给脚本执行权限
chmod +x /root/jmeter/battest1.sh
# 直接执行
/root/jmeter/battest.sh1、直接ip地址测试
120.76.53.248
139.9.220.83
2、https测试
3、token测试
4、redis测试
5、不同连接数测试
/api/CommonService/common/sample
/api/CommonService/common/authorized
/api/CommonService/ModelProp/RedisModelTableHeadersByName?moduleName=WaterSupervision&modelName=Section
/api/CommonService/ModelProp/modelTableHeadersByName?moduleName=WaterSupervision&modelName=Section
/api/WaterSupervision/Section/TableCLI 模式可选参数
| 字段 | 含义 |
|---|---|
| -n | 指定 JMeter 将在 cli 模式下运行 |
| -t | 包含测试计划的 jmx 文件名称 |
| -l | 记录测试结果的 jtl 文件名称 |
| -j | 记录 Jmeter 运行日志的文件名称 |
| -g | 输出报告文件( .csv 文件) |
| -e | 生成 html 格式的测试报表 |
| -o | 生成测试报表的文件夹文件夹不存在或为空 |
服务器相关参数
| 字段 | 含义 |
|---|---|
| -H | 代理服务器的 host 或 ip |
| -P | 代理服务器的 port |
| -r | 指定所有远程服务器中运行测试 |
| -R | 在指定的远程服务器中运行测试 |
| -X | 服务器运行完脚本后自动停止 jmeter-server |
属性参数
Java 系统属性和 JMeter 属性可以直接通过以下命令进行覆盖,而不用手动修改 jmeter.properties
| 格式 | 含义 |
|---|---|
| -D[prop_name]=[value] | 定义一个 Java 系统属性值 |
| -J[prop_name]=[value] | 定义本地 JMeter 属性 |
| -G[prop_name]=[value] | 定义要发送到所有远程服务器的 JMeter 属性 |
| -G[propertyfile] | 定义一个包含 JMeter 属性的文件,该文件将发送到所有远程服务器 |
| -L[category]=[priority] | 覆盖日志记录设置,将特定类别设置为给定的优先级设置根日志记录级别 |
rabbitmq 测试
bash
docker pull pivotalrabbitmq/perf-test:latest
docker run -it --rm pivotalrabbitmq/perf-test:latest
# 需设置test测试账号,使用宿主机的网络,这样可以用 localhost 访问,60秒,条件:使用2个发布者和10个消费者:
docker run -it --rm \
--network host \
pivotalrabbitmq/perf-test \
-h "amqp://test:testpassword@localhost:8023/vhost" \
-x 2 -y 10 -u "throughput-test-1" -a --id "test-1" -z 60
# 用localhost,呑吐量8000,条件:一个生产者,一个消费者,消息大小从默认(12字节)更改为4 kB
# 用shuze.net:8023,呑吐量50,abp中可用容器名代替网址shuze.net:8023,但端口需用5672
docker run -it --rm \
--network host \
pivotalrabbitmq/perf-test \
-h "amqp://test:testpassword@shuze.net:8023/vhost" \
-x 1 -y 1 -u "throughput-test-1-1-4096" -a --id "test 1-1 4096" -s 4096 -z 60
综上,在abp的rabbitmq的地址应用容器名称,这样就是localhost,参考:rabbitmq 性能测试 PerfTest 吞吐率最全评测 - 代号尚行 (claves.cn),RabbitMQ 性能测试工具的使用_rabbitmq 测试工具-CSDN 博客
- 执行 PerfTest 最基本的方法是指定要使用的 URL(ampq(s)😕/username:password@host:port/vhostname)、生产者数量(比如说 1)和消费者数量(比如 2)。注意,rabbitmq java 客户端能够达到较高的发布速度(每个 connection 每秒发布可以达到 80000 到 90000 个消息),这是在带宽充足,并且关闭了一些安全措施(生产者确认),因此,没必要提供过量的生产者(除非那是一个确定的测试目标)。
redis 测试
# 测试不同数据大小的性能曲线(本地)
for size in 50 100 200 500 1000 2000 10000 50000 1024000; do
echo "Data size: $size bytes"
docker exec -it base-redis redis-benchmark \
-h localhost -p 6379 -a Limd@12345 \
-t set -d $size -c 10 -n 1000 -P 1 -q
done
# 测试不同数据大小的性能曲线(远程)
for size in 50 100 200 500 1000 2000 10000 50000 1024000; do
echo "Data size: $size bytes"
docker exec -it base-redis redis-benchmark \
-h shuze.net -p 8022 -a Limd@12345 \
-t set -d $size -c 10 -n 1000 -P 1 -q
done
# 2. 测试不同并发级别
for clients in 10 50 100 200; do
echo "Clients: $clients"
docker exec -it base-redis redis-benchmark \
-a "Limd@12345" -t set -c $clients -n 1000 -P 8 -q
done
# 测试临界点(找出性能下降的转折点)
for clients in 300 400 500 1000; do
echo "Clients: $clients"
docker exec -it base-redis redis-benchmark \
-a "Limd@12345" -t set -c $clients -n 50000 -P 8 -q
donepostgresql测试
连接字符串
abp中数据库连接字符串在开发环境中无所谓,但在发布环境中很关键,设置连接池后,带数据库的操作呑吐量有明显增加。
"ConnectionStrings": {
"Default": "Server=postgresql-cluster;Port=5432;Database=MyProjectDB;User Id=abp_app;Password=P@ssw0rd!123;Pooling=true;Maximum Pool Size=150;Minimum Pool Size=20;Connection Lifetime=300;Command Timeout=600;Timeout=30;Keepalive=60;",
},
portgresql docker-compose
command:
- "postgres"
- "-c"
- "shared_buffers=512MB" # 从128MB提升到512MB
- "-c"
- "work_mem=32MB" # 从4MB提升到32MB
- "-c"
- "effective_cache_size=2GB" # 从4GB修正为2GB
- "-c"
- "max_connections=100"
- "-c"
- "random_page_cost=1.1" # SSD优化
- "-c"
- "checkpoint_timeout=10min" # 减少检查点频率pgbench
是PostgreSQL自带的压测工具。
# 1. 创建 pgbench 数据库
createdb -h localhost -U postgres pgbench
# 2. 现在初始化 pgbench
pgbench -h localhost -U postgres -i pgbench
# 基本测试(运行60秒)
pgbench -h localhost -U postgres -T 60 pgbench
# 并发测试(10个客户端,2个线程,运行60秒)
pgbench -h localhost -U postgres -c 10 -j 2 -T 60 -r pgbench
# 只读测试
pgbench -h localhost -U postgres -S -T 60 pgbench# 进入PostgreSQL容器
docker exec -it base-postgres bash
# 连接到PostgreSQL
psql -U postgres -d postgres三、连接池优化参数:高并发场景的利器
在高并发应用中,合理配置连接池参数可以显著提高系统性能和资源利用率。
pool_size参数定义了连接池中维护的常驻连接数量。适当增大这个值可以减少连接建立的开销,如pool_size=20表示始终保持 20 个活跃连接。但设置过大则会浪费服务器资源。
reserve_pool参数指定了连接池的"备用容量",当常规连接耗尽时可以使用这些额外连接。例如reserve_pool=5表示在常规连接用尽后,还可以再创建 5 个连接应对突发流量。
max_db_connections参数限制应用程序到数据库的最大连接数,防止连接数失控导致数据库过载。这个值需要根据数据库服务器的配置和负载能力合理设置。
pool_mode参数决定了连接池的工作模式,主要有三种:
session 模式:连接在整个会话期间保持,传统应用,长会话
transaction 模式:连接仅在事务期间保持,Web 应用,短事务
statement 模式:连接仅在执行语句期间保持,只读查询,简单语句
不同的模式适用于不同场景,transaction 模式适合短事务应用,可以最大化连接复用率。
PostgreSQL作战指南(postgresql.conf):
max_connections = 500 # 更高的连接上限
max_worker_processes = 8 # 并行工作进程数
effective_cache_size = 8GB # 优化查询计划
synchronous_commit = off # 异步提交提升吞吐