目录
前言
本教程内容庞大,所以尽量写的精简,没有写出脚本的具体编写步骤,有兴趣的朋友可以下载Demo后和教程对照着看。
请求的服务端,是通过服务端模拟器来生成的。可以下载Mock服务端模拟器,设定与教程相同的请求地址来学习。
Demo下载地址:点击下载
Mock服务端模拟器:点击下载
下载安装Jmeter
计算机上已装好Jmeter的请跳过此步骤。本教程是根据Jmeter5.0编写的,其他版本可能有出入。
- 访问官网并下载,培养大家自己动手的习惯,就不给出官网链接了,自己百度吧。
Binaries的意思是发行版。Source是源码,用于二次开发。
- 解压出来就算装好了。
- 配置环境变量(计算机右键->属性->高级系统设置->环境变量)
新建一个环境变量 变量名JMETER_HOME 变量值:你解压出来的目录
编辑Path变量 追加一段内容;%JMETER_HOME%\bin
安装相关插件
下载插件管理工具
- 百度一下jmeter plugins找到Jmeter插件官网,下载plugins-manager.jar(插件管理工具)
- 下载好了之后,放进Jmeter安装路径的/lib/ext目录下,再重启Jmeter
安装性能测试相关插件
- 打开插件管理工具 (选项->Plugins Manager->Available Plugins)
- 根据需求勾选以下插件:
插件名 | - |
---|---|
Custom Thread Groups | - 个人觉得最好用的性能测试线程组 |
3 Basic Graphs | - 活动线程数变化曲线 |
- | - 响应时间变化曲线 |
- | - 每秒事务处理率(TPS) |
Composite Timeline Graph | - 把多个图形监听器组合起来 |
PerfMon (Servers Performance Monitoring) | - 远程监听服务器资源使用率 |
Command-Line Graph Plotting Tool | - 可以手动把jtl或csv文件转化成图片(主要用于PerfMon结果生成图形) |
*以上插件都是按需勾选,譬如你的服务器是放在阿里云上的,自带了资源监控,就不需要PerfMon插件了。
安装监控服务器资源程序
- PerfMon还需要额外的一个程序:ServerAgent 它的功能是获取当前计算机的CPU、RAM、I/O等使用情况
我们在插件中找到,访问它的介绍页面
- 往下拉,在Installation中点击here,进入下载页面
- 点击下载最新版。
- 这是一个独立程序,它需要放到服务器上运行,然后测试过程中监听服务器的资源使用情况。
*建议本地也放一份,这个后面会用到。
- 再次强调,这个程序是应该放在被测对象机器上的。
*这里用于演示,请求的是127.0.0.1的地址,所以就在本机运行了。实际工作中客户机和服务器肯定是分开的。
设计一个性能测试脚本
性能测试场景
- 用户定义变量配置元件,可以设置一些环境变量,让我们快速切换测试环境。
- 我喜欢再定义一个HTTP请求默认值配置元件,因为这样之后的Sampler就不用再写协议、IP和端口号了
- Concurrency Thread Group 最好用的性能测试场景线程组
Target Concurrency是 总线程数
Ramp Up Time(min) 是 总运行时间(单位分钟)
Ramp-Up Steps Count 是份数
Hold Target Rate Time(min)是保持执行时间
实际意义就是,总共启动500个线程,执行5分钟,分成10个阶段启动,最后持续0分钟结束。
性能测试监听器
- 每秒活动线程变化,基本和设置的场景一致
- 每秒响应时间变化
- 每秒事务处理率(TPS)
- 组合图形
结合以上3个监听器我们可以看出,随着活动线程数的不断增加,响应时间越来越高,但TPS保持稳定没有太大变化。
- 服务端CPU和RAM
这里因为测试对象也在本地,所以写的localhost,实际应该填写运行ServerAgent的服务端地址。
- 硬盘I/O和网络I/O
建议和CPU分开来监听,因为CPU和RAM峰值100,而I/O峰值数百万。放在一起看起来不方便。
- 如果你需要使用PerfMon监听器,那么建议你在测试计划中定义一个脚本路径地址的变量。__P()函数用来用cmd接收参数。然后在PerfMon监听器中,使用这个路径,把监听结果保存成文件。这样配置后,我们通过非GUI模式运行脚本时,可以把服务器资源使用情况转化成图表。
编写启动器
- 根据我长期以来经验,并不断完善,我建议可以参考我写的批处理脚本
- 生成当前日志 是为了多次测试结果不覆盖,并保留归档
- 配置地址 jmxPath是为了把PerfMon监听器结果保存,否则直接用.就能获取到当前路径了。
jmeterPath也是为了把PerfMon监听器的结果转化成图表图片。 - 创建日期文件夹 用于存放测试结果
- 执行Jmeter
- 生成监听器截图 (*Jmeter5.0必须要安装"Command-Line Graph Plotting Tool"插件,才能用这个命令)
- 日志存档 把JMeter.log文件放入日期文件夹。创建Release文件夹,用于保存最新测试结果。
@echo off
rem 生成当前日期
set date=%date:~0,4%%date:~5,2%%date:~8,2%
if "%time:~0,2%" lss "10" (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
set time=%hour%%time:~3,2%%time:~6,2%
set d=%date%%time%
echo 当前日期: %d%
rem 配置地址
set jmxPath="E:\Desktop\博文\Demo"
set jmeterPath="F:\apache-jmeter-5.0"
rem 创建日期文件夹
mkdir %jmxPath%\%d%
if not exist %jmxPath%\%d%\PerfMon mkdir %jmxPath%\%d%\PerfMon >nul
rem 执行Jmeter
call jmeter -JjmxPath="%jmxPath%\%d%" -n -t %jmxPath%\Demo.jmx -l %jmxPath%\%d%\Result.jtl -e -o %jmxPath%\%d%\Report
rem 生成监听器截图(需要修改版本号)
call java -jar %jmeterPath%\lib\cmdrunner-2.2.jar --tool Reporter --generate-png %jmxPath%\%d%\CPUMemory.png --input-jtl %jmxPath%\%d%\PerfMon\CPUMemory.jtl --plugin-type PerfMon
call java -jar %jmeterPath%\lib\cmdrunner-2.2.jar --tool Reporter --generate-png %jmxPath%\%d%\IO.png --input-jtl %jmxPath%\%d%\PerfMon\IO.jtl --plugin-type PerfMon
:: 日志存档
move %jmxPath%\jmeter.log %jmxPath%\%d% >nul
if not exist %jmxPath%\Release mkdir %jmxPath%\Release >nul
xcopy /Y %jmxPath%\%d% %jmxPath%\Release /s /f /h >nul
:: pause
- 如果不用PerfMon插件、不需要生成CPU&RAM等资源情况,可以参考这种写法
@echo off
rem 生成当前日期
set date=%date:~0,4%%date:~5,2%%date:~8,2%
if "%time:~0,2%" lss "10" (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
set time=%hour%%time:~3,2%%time:~6,2%
set d=%date%%time%
echo 当前日期: %d%
rem 创建日期文件夹
mkdir %d%
rem 执行Jmeter
call jmeter -n -t Demo.jmx -l %d%\Result.jtl -e -o %d%\Report
:: 日志存档
move jmeter.log %d% >nul
if not exist Release mkdir Release >nul
xcopy /Y %d% Release /s /f /h >nul
:: pause
- 以上写法是把脚本和测试结果放在一个路径下的。如果要把测试报告放在其他地址下(譬如放到Jenkins上,肯定要测试结果和脚本分离了),可以做相应修改。同时还可以对多余测试报告进行清除。
@echo off
rem 生成当前日期
set date=%date:~0,4%%date:~5,2%%date:~8,2%
if "%time:~0,2%" lss "10" (set hour=0%time:~1,1%) else (set hour=%time:~0,2%)
set time=%hour%%time:~3,2%%time:~6,2%
set d=%date%%time%
echo 当前日期: %d%
rem 配置地址
set reportPath="E:\Desktop\API_TEST_RESULT"
rem 创建日期文件夹
mkdir %reportPath%\%d%
rem 执行Jmeter
call jmeter -n -t Demo.jmx -l %reportPath%\%d%\Result.jtl -e -o %reportPath%\%d%\Report
:: 日志存档
move jmeter.log %reportPath%\%d% >nul
if not exist %reportPath%\Release mkdir %reportPath%\Release >nul
xcopy /Y %reportPath%\%d% %reportPath%\Release /s /f /h >nul
:: 清除多余历史测试报告
for /f "skip=8 delims=" %%a in ('dir /b /ad /o-d "%reportPath%"\*') do @rd /s /q "%reportPath%"\"%%a" && echo del %%a
:: pause
性能测试过程
执行测试
- 有了批处理程序,我们可以快速的调整和反复执行不同场景。
前面演示为了方便,实际上我们通常把线程组里的参数(总线程数、总时间、切割份数)也用__P()函数来传递。这样我们放到Jenkins服武器上或需要多次执行时,只需要修改.bat中的参数就可以改变执行的场景。
- 执行完之后就会有一个日期文件夹来存放本次测试结果
- 直接把PerfMon中的CPU等信息转化成了图片。
测试报告
- 报表部分有PASS率、平均响应时间、90%响应时间等信息。如果有错误,下方也有错误信息。
为什么我的报告是中文,你的报告是英文?因为我自己汉化了。
汉化方法见:https://blog.csdn.net/tomoya_chen/article/details/56481479
最新完全汉化包:下载页面
- 每秒活动线程变化
- 每秒响应时间变化
- 每秒事务处理率(TPS)
分析测试结果
- 理论
- 分析
以刚才的测试报告为例,由于测试时间比较短,尾部释放线程阶段不参考。但仍然可以看出一些趋势。
- 随着用户数越来越多,TPS也越来越高,但是在33分开始趋于平缓。甚至在34分开始,明明活动线程数上升,但TPS反而下降的不合理情况。
- 34分响应时间变化倒是不太明显,但是在35分开始急剧上升了,此时TPS也是继续下降,活动线程数为500。
如果忽略脚本释放线程的部分,可以得出初步结论,系统最多能支持每秒处理22个事务,即TPS=22,此时对应的用户数在每秒250~300人。更多用户的情况下,系统还不至于崩溃,但响应时间会很慢。
所以,这就是真实结果了吗?不是,我们再来看一下CPU情况。
- 服务器CPU一直在65%~75%之间,在刚才分析结果的拐点区仍然没有继续升高。这说明服务器并没有太吃力。
什么原因呢?有可能有以下几种情况:
- 测试机本身机能受限,测试过程中自己都卡的不行了,导致发出到服务器的请求没有那么密集,没有产生那么大的压力。
- 网络I/O的问题,网络带宽上下行满了,导致响应时间变长,但本身服务器性能空闲。
- 服务器对请求的IP或终端有特殊处理,限制 了最大TPS。
- 其他
性能测试易学难精,跑完脚本给开发看固然简单,但自己分析的话需要的知识面非常广,但是响应时间就包含了七八层。我推测本次测试应该是第1种情况,因为NET I/O并不高。还需要加大线程数、延长测试时间继续测试来观察一下,甚至需要用到分布式方法进行测试。第四种情况是之前测试一个WebSocket接口时发现,服务端对单个终端发出的请求会限制TPS。当时我的解决办法是写了一个并发启动脚本,让一台机器跑20个jmeter脚本,8台机器模拟160个终端,最终才测出服务器的TPS在1400多,否则无论怎么测都是20TPS。
- 总结
Jmeter在规范了插件管理之后,把活动线程数、响应时间、TPS打包成一个3 Basic Graphs。就是因为日常测试中基本就是靠这3个监听器完成初步分析。而为什么监听服务器资源也很重要呢?Jmeter在规范了插件管理之后,把活动线程数、响应时间、TPS打包成一个3 Basic Graphs。就是因为日常测试中基本就是靠这3个监听器完成初步分析。而为什么监听服务器资源也很重要呢?
因为:
1.我们要验证测试结果是否准确。
2.真的对服务器造成压力了,我们要找到CPU满载的那个时间点。再结合以上3个监听器一起分析。