编写此文,主要想通过这种方式,记录自己研究Jmeter的过程和实用方法技巧。2022.01.20
第一步:要使用Jmeter,先从官方下载最新版本,下载链接Apache JMeter - Download Apache JMeter;
第二步:解压压缩包后,运行bin文件夹下的jmeter.bat或jmeter.sh,根据所使用的电脑平台决定;这里得提前安装JDK/JRE,具体的方法就不说了,太过于基础了;
第三步:下载安装Jmeter插件管理器Install :: JMeter-Plugins.org,将jar包放入Jmeter的lib/ext文件夹目录下,重启Jmeter;(Download plugins-manager.jar and put it into lib/ext directory, then restart JMeter.)
第四步:用Jmeter插件管理器,
;
第五步:安装自己所需的插件,常用插件列表参考如下:
;
第六步:根据自己所需做的测试对象类型,选择不同的协议(插件)进行脚本开发(录制);这里以HTTP协议脚本录制为例,测试计划(TestPlan)中需要的基础组件参考如下:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.1"> 3 <hashTree> 4 <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true"> 5 <stringProp name="TestPlan.comments"></stringProp> 6 <boolProp name="TestPlan.functional_mode">false</boolProp> 7 <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp> 8 <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> 9 <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> 10 <collectionProp name="Arguments.arguments"/> 11 </elementProp> 12 <stringProp name="TestPlan.user_define_classpath"></stringProp> 13 </TestPlan> 14 <hashTree> 15 <ProxyControl guiclass="ProxyControlGui" testclass="ProxyControl" testname="HTTP(S) Test Script Recorder" enabled="true"> 16 <stringProp name="ProxyControlGui.port">8888</stringProp> 17 <collectionProp name="ProxyControlGui.exclude_list"/> 18 <collectionProp name="ProxyControlGui.include_list"/> 19 <boolProp name="ProxyControlGui.capture_http_headers">true</boolProp> 20 <intProp name="ProxyControlGui.grouping_mode">0</intProp> 21 <boolProp name="ProxyControlGui.add_assertion">false</boolProp> 22 <stringProp name="ProxyControlGui.sampler_type_name"></stringProp> 23 <boolProp name="ProxyControlGui.sampler_redirect_automatically">false</boolProp> 24 <boolProp name="ProxyControlGui.sampler_follow_redirects">true</boolProp> 25 <boolProp name="ProxyControlGui.use_keepalive">true</boolProp> 26 <boolProp name="ProxyControlGui.detect_graphql_request">true</boolProp> 27 <boolProp name="ProxyControlGui.sampler_download_images">false</boolProp> 28 <intProp name="ProxyControlGui.proxy_http_sampler_naming_mode">0</intProp> 29 <stringProp name="ProxyControlGui.default_encoding"></stringProp> 30 <stringProp name="ProxyControlGui.proxy_prefix_http_sampler_name"></stringProp> 31 <stringProp name="ProxyControlGui.proxy_pause_http_sampler"></stringProp> 32 <boolProp name="ProxyControlGui.notify_child_sl_filtered">false</boolProp> 33 <boolProp name="ProxyControlGui.regex_match">false</boolProp> 34 <stringProp name="ProxyControlGui.content_type_include"></stringProp> 35 <stringProp name="ProxyControlGui.content_type_exclude"></stringProp> 36 </ProxyControl> 37 <hashTree/> 38 <com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup guiclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroupGui" testclass="com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup" testname="bzm - Concurrency Thread Group" enabled="true"> 39 <elementProp name="ThreadGroup.main_controller" elementType="com.blazemeter.jmeter.control.VirtualUserController"/> 40 <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> 41 <stringProp name="TargetLevel"></stringProp> 42 <stringProp name="RampUp"></stringProp> 43 <stringProp name="Steps"></stringProp> 44 <stringProp name="Hold"></stringProp> 45 <stringProp name="LogFilename"></stringProp> 46 <stringProp name="Iterations"></stringProp> 47 <stringProp name="Unit">M</stringProp> 48 </com.blazemeter.jmeter.threads.concurrency.ConcurrencyThreadGroup> 49 <hashTree> 50 <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> 51 <collectionProp name="HeaderManager.headers"/> 52 </HeaderManager> 53 <hashTree/> 54 <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true"> 55 <collectionProp name="CookieManager.cookies"/> 56 <boolProp name="CookieManager.clearEachIteration">false</boolProp> 57 <boolProp name="CookieManager.controlledByThreadGroup">false</boolProp> 58 </CookieManager> 59 <hashTree/> 60 <TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="001_Login" enabled="true"> 61 <boolProp name="TransactionController.includeTimers">false</boolProp> 62 <boolProp name="TransactionController.parent">false</boolProp> 63 </TransactionController> 64 <hashTree> 65 <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true"> 66 <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true"> 67 <collectionProp name="Arguments.arguments"/> 68 </elementProp> 69 <stringProp name="HTTPSampler.domain"></stringProp> 70 <stringProp name="HTTPSampler.port"></stringProp> 71 <stringProp name="HTTPSampler.protocol"></stringProp> 72 <stringProp name="HTTPSampler.contentEncoding"></stringProp> 73 <stringProp name="HTTPSampler.path"></stringProp> 74 <stringProp name="HTTPSampler.method">GET</stringProp> 75 <boolProp name="HTTPSampler.follow_redirects">true</boolProp> 76 <boolProp name="HTTPSampler.auto_redirects">false</boolProp> 77 <boolProp name="HTTPSampler.use_keepalive">true</boolProp> 78 <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> 79 <stringProp name="HTTPSampler.embedded_url_re"></stringProp> 80 <stringProp name="HTTPSampler.connect_timeout"></stringProp> 81 <stringProp name="HTTPSampler.response_timeout"></stringProp> 82 </HTTPSamplerProxy> 83 <hashTree> 84 <JSONPostProcessor guiclass="JSONPostProcessorGui" testclass="JSONPostProcessor" testname="JSON Extractor" enabled="true"> 85 <stringProp name="JSONPostProcessor.referenceNames"></stringProp> 86 <stringProp name="JSONPostProcessor.jsonPathExprs"></stringProp> 87 <stringProp name="JSONPostProcessor.match_numbers"></stringProp> 88 </JSONPostProcessor> 89 <hashTree/> 90 <BoundaryExtractor guiclass="BoundaryExtractorGui" testclass="BoundaryExtractor" testname="Boundary Extractor" enabled="true"> 91 <stringProp name="BoundaryExtractor.useHeaders">false</stringProp> 92 <stringProp name="BoundaryExtractor.refname"></stringProp> 93 <stringProp name="BoundaryExtractor.lboundary"></stringProp> 94 <stringProp name="BoundaryExtractor.rboundary"></stringProp> 95 <stringProp name="BoundaryExtractor.default"></stringProp> 96 <boolProp name="BoundaryExtractor.default_empty_value">false</boolProp> 97 <stringProp name="BoundaryExtractor.match_number"></stringProp> 98 </BoundaryExtractor> 99 <hashTree/> 100 <RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true"> 101 <stringProp name="RegexExtractor.useHeaders">false</stringProp> 102 <stringProp name="RegexExtractor.refname"></stringProp> 103 <stringProp name="RegexExtractor.regex"></stringProp> 104 <stringProp name="RegexExtractor.template"></stringProp> 105 <stringProp name="RegexExtractor.default"></stringProp> 106 <stringProp name="RegexExtractor.match_number"></stringProp> 107 </RegexExtractor> 108 <hashTree/> 109 <JSR223PostProcessor guiclass="TestBeanGUI" testclass="JSR223PostProcessor" testname="JSR223 PostProcessor" enabled="true"> 110 <stringProp name="cacheKey">true</stringProp> 111 <stringProp name="filename"></stringProp> 112 <stringProp name="parameters"></stringProp> 113 <stringProp name="script"></stringProp> 114 <stringProp name="scriptLanguage">groovy</stringProp> 115 </JSR223PostProcessor> 116 <hashTree/> 117 </hashTree> 118 <DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="true"> 119 <boolProp name="displayJMeterProperties">false</boolProp> 120 <boolProp name="displayJMeterVariables">true</boolProp> 121 <boolProp name="displaySystemProperties">false</boolProp> 122 </DebugSampler> 123 <hashTree/> 124 </hashTree> 125 <TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="002_TestCase_01" enabled="true"> 126 <boolProp name="TransactionController.includeTimers">false</boolProp> 127 <boolProp name="TransactionController.parent">false</boolProp> 128 </TransactionController> 129 <hashTree/> 130 </hashTree> 131 <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> 132 <boolProp name="ResultCollector.error_logging">false</boolProp> 133 <objProp> 134 <name>saveConfig</name> 135 <value class="SampleSaveConfiguration"> 136 <time>true</time> 137 <latency>true</latency> 138 <timestamp>true</timestamp> 139 <success>true</success> 140 <label>true</label> 141 <code>true</code> 142 <message>true</message> 143 <threadName>true</threadName> 144 <dataType>true</dataType> 145 <encoding>false</encoding> 146 <assertions>true</assertions> 147 <subresults>true</subresults> 148 <responseData>false</responseData> 149 <samplerData>false</samplerData> 150 <xml>false</xml> 151 <fieldNames>true</fieldNames> 152 <responseHeaders>false</responseHeaders> 153 <requestHeaders>false</requestHeaders> 154 <responseDataOnError>false</responseDataOnError> 155 <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> 156 <assertionsResultsToSave>0</assertionsResultsToSave> 157 <bytes>true</bytes> 158 <sentBytes>true</sentBytes> 159 <url>true</url> 160 <threadCounts>true</threadCounts> 161 <idleTime>true</idleTime> 162 <connectTime>true</connectTime> 163 </value> 164 </objProp> 165 <stringProp name="filename"></stringProp> 166 </ResultCollector> 167 <hashTree/> 168 <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.TransactionsPerSecondGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="jp@gc - Transactions per Second" enabled="true"> 169 <boolProp name="ResultCollector.error_logging">false</boolProp> 170 <objProp> 171 <name>saveConfig</name> 172 <value class="SampleSaveConfiguration"> 173 <time>true</time> 174 <latency>true</latency> 175 <timestamp>true</timestamp> 176 <success>true</success> 177 <label>true</label> 178 <code>true</code> 179 <message>true</message> 180 <threadName>true</threadName> 181 <dataType>true</dataType> 182 <encoding>false</encoding> 183 <assertions>true</assertions> 184 <subresults>true</subresults> 185 <responseData>false</responseData> 186 <samplerData>false</samplerData> 187 <xml>false</xml> 188 <fieldNames>true</fieldNames> 189 <responseHeaders>false</responseHeaders> 190 <requestHeaders>false</requestHeaders> 191 <responseDataOnError>false</responseDataOnError> 192 <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> 193 <assertionsResultsToSave>0</assertionsResultsToSave> 194 <bytes>true</bytes> 195 <sentBytes>true</sentBytes> 196 <url>true</url> 197 <threadCounts>true</threadCounts> 198 <idleTime>true</idleTime> 199 <connectTime>true</connectTime> 200 </value> 201 </objProp> 202 <stringProp name="filename"></stringProp> 203 <longProp name="interval_grouping">1000</longProp> 204 <boolProp name="graph_aggregated">false</boolProp> 205 <stringProp name="include_sample_labels"></stringProp> 206 <stringProp name="exclude_sample_labels"></stringProp> 207 <stringProp name="start_offset"></stringProp> 208 <stringProp name="end_offset"></stringProp> 209 <boolProp name="include_checkbox_state">false</boolProp> 210 <boolProp name="exclude_checkbox_state">false</boolProp> 211 </kg.apc.jmeter.vizualizers.CorrectedResultCollector> 212 <hashTree/> 213 <kg.apc.jmeter.vizualizers.CorrectedResultCollector guiclass="kg.apc.jmeter.vizualizers.ResponseTimesOverTimeGui" testclass="kg.apc.jmeter.vizualizers.CorrectedResultCollector" testname="jp@gc - Response Times Over Time" enabled="true"> 214 <boolProp name="ResultCollector.error_logging">false</boolProp> 215 <objProp> 216 <name>saveConfig</name> 217 <value class="SampleSaveConfiguration"> 218 <time>true</time> 219 <latency>true</latency> 220 <timestamp>true</timestamp> 221 <success>true</success> 222 <label>true</label> 223 <code>true</code> 224 <message>true</message> 225 <threadName>true</threadName> 226 <dataType>true</dataType> 227 <encoding>false</encoding> 228 <assertions>true</assertions> 229 <subresults>true</subresults> 230 <responseData>false</responseData> 231 <samplerData>false</samplerData> 232 <xml>false</xml> 233 <fieldNames>true</fieldNames> 234 <responseHeaders>false</responseHeaders> 235 <requestHeaders>false</requestHeaders> 236 <responseDataOnError>false</responseDataOnError> 237 <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> 238 <assertionsResultsToSave>0</assertionsResultsToSave> 239 <bytes>true</bytes> 240 <sentBytes>true</sentBytes> 241 <url>true</url> 242 <threadCounts>true</threadCounts> 243 <idleTime>true</idleTime> 244 <connectTime>true</connectTime> 245 </value> 246 </objProp> 247 <stringProp name="filename"></stringProp> 248 <longProp name="interval_grouping">500</longProp> 249 <boolProp name="graph_aggregated">false</boolProp> 250 <stringProp name="include_sample_labels"></stringProp> 251 <stringProp name="exclude_sample_labels"></stringProp> 252 <stringProp name="start_offset"></stringProp> 253 <stringProp name="end_offset"></stringProp> 254 <boolProp name="include_checkbox_state">false</boolProp> 255 <boolProp name="exclude_checkbox_state">false</boolProp> 256 </kg.apc.jmeter.vizualizers.CorrectedResultCollector> 257 <hashTree/> 258 <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="Aggregate Report" enabled="true"> 259 <boolProp name="ResultCollector.error_logging">false</boolProp> 260 <objProp> 261 <name>saveConfig</name> 262 <value class="SampleSaveConfiguration"> 263 <time>true</time> 264 <latency>true</latency> 265 <timestamp>true</timestamp> 266 <success>true</success> 267 <label>true</label> 268 <code>true</code> 269 <message>true</message> 270 <threadName>true</threadName> 271 <dataType>true</dataType> 272 <encoding>false</encoding> 273 <assertions>true</assertions> 274 <subresults>true</subresults> 275 <responseData>false</responseData> 276 <samplerData>false</samplerData> 277 <xml>false</xml> 278 <fieldNames>true</fieldNames> 279 <responseHeaders>false</responseHeaders> 280 <requestHeaders>false</requestHeaders> 281 <responseDataOnError>false</responseDataOnError> 282 <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> 283 <assertionsResultsToSave>0</assertionsResultsToSave> 284 <bytes>true</bytes> 285 <sentBytes>true</sentBytes> 286 <url>true</url> 287 <threadCounts>true</threadCounts> 288 <idleTime>true</idleTime> 289 <connectTime>true</connectTime> 290 </value> 291 </objProp> 292 <stringProp name="filename"></stringProp> 293 </ResultCollector> 294 <hashTree/> 295 </hashTree> 296 </hashTree> 297 </jmeterTestPlan>
1. 为了录制脚本,需要添加HTTP(S) Test Script Recorder;
2. 为了可以调整加压模型(加压曲线),需要添加 bzm - Concurrency Thread Group 并发线程组;
3. 为了HTTP Header 和 Cookie统一管理,需要添加 HTTP Header Manager 及 HTTP Cookie Manager,添加后所有HTTP请求都会使用相同的Cookie值和Header参数,否则每个请求都会用不同的Cookie,进而出现登录失效的情况;
4. 为了定义 事务(Transaction) 单元,需要添加 Transaction Logical 控制器(例如:001_Login)表示 登录 事务,其他的事务,(例如002_TestCase_01)需自己根据实际测试需要添加;
5. 为了进行动态参数获取和替换,以达到参数化的效果,需要合理使用JSON、Boundary、Regular Expression、JSR223 PostProcessor等后置或前置处理步骤;
6. 为了调试参数值和打印日志,需要Debug Sampler采样器,以配合上一个(5)中加入的后置、前置操作调试;
7. 为了在GUI环境下调试方便,需要添加View Result Tree监听器,这样可以看到每个请求是否成功(绿色),失败(红色),并看到Request 和 Response的Header、Body信息,调试使用;
8. 实际执行并发测试时,需要看 jp@gc - Transactions per Second 及 jp@gc - Response Times Over Time,即每秒事务数(TPS)和事务响应时间(RT);聚合报告(Aggregate Report)可以作为统计量分析事务成功、失败(Pass/Fail)比率;
划重点:最开始使用Jmeter或使用中文界面时,经常会找不到所需的组件位置,这里给出以上组件的位置:
1. 并发线程组:
2. 察看结果树,在运行调试时使用:
3. Header, Cookie, Cache管理器,在保证所有请求都使用同一Cookie信息时使用,可以解决一般的登录问题:
4. 逻辑事务控制器,与Loadrunner的事务等效,可以理解为最终测试结果图里的事务名称,记录了这个逻辑事务开始时间戳到结束时间戳之间的运行时间;即Transaction ResponseTime
6. Debug Sample,调试采样器,通常用来调试和打印我们定义的变量或从请求中获取的变量值;
7. 常用的请求返回数据提取器,根据服务器返回数据的不同类型(文本?Json?HTML?XML等等),选择不同的提取器:
第七步:开始脚本录制和事务划分,调试脚本;
调试脚本常用到几个监听器和调试器,Result Tree View,Debug,详见上个章节;
第八步:执行测试,想和Loadrunner一样进行场景测试,就得灵活配置执行线程组,常用的是并发线程组,介绍和用法参考https://cloud.tencent.com/developer/article/1640890:
第九步:命令行方式执行测试,并察看执行完成的报告结果数据;参考Jmeter系列(40)- 详解 Jmeter CLI 模式 - 小菠萝测试笔记 - 博客园 (cnblogs.com)
第十步:需要分布式执行大批量测试,参考Jmeter系列(39)- Jmeter 分布式测试 - 小菠萝测试笔记 - 博客园 (cnblogs.com)
第十一步:由了RT和TPS,还差CPU与MEM监控,
Linux/Unix请参考nmon监控方法Jmeter系列(38)- 详解性能监控工具 nmon - 小菠萝测试笔记 - 博客园 (cnblogs.com)
当然也可以用Jmeter提供的监控方法,参考Jmeter系列(35)- 使用 ServerAgent 监控服务器 - 小菠萝测试笔记 - 博客园 (cnblogs.com),如果遇到了监控问题,请参考接下来的 ※ 划重点 ※
细节的参考,给两个地址,一个是官方文档Apache JMeter - User's Manual,一个是博客园小伙伴(一位阿里的测开工程师)整理的专题测试高级进阶技能系列 - Jmeter - 随笔分类(第3页) - 小菠萝测试笔记 - 博客园 (cnblogs.com);
※ 划重点 ※
监控CPU/MEM遇到的问题解决方法:
错误现象:安装了 PerfMon (Servers Performance Monitoring) 插件后,添加了服务器资源监控,点击开始后无响应,Jmeter日志控制台报错如下:
ERROR o.a.j.JMeter: Uncaught exception in thread Thread[StandardJMeterEngine,6,main]
java.lang.NoSuchMethodError: org.apache.jmeter.samplers.SampleSaveConfiguration.setFormatter(Ljava/text/DateFormat;)V
at kg.apc.jmeter.JMeterPluginsUtils.doBestCSVSetup(JMeterPluginsUtils.java:272) ~[JMeterPlugins-Extras.jar:?]
at kg.apc.jmeter.perfmon.PerfMonCollector.setupSaving(PerfMonCollector.java:136) ~[jmeter-plugins-perfmon-2.1.jar:?]
at kg.apc.jmeter.perfmon.PerfMonCollector.testStarted(PerfMonCollector.java:113) ~[jmeter-plugins-perfmon-2.1.jar:?]
at org.apache.jmeter.reporters.ResultCollector.testStarted(ResultCollector.java:350) ~[ApacheJMeter_core.jar:5.4.1]
at kg.apc.jmeter.vizualizers.CorrectedResultCollector.testStarted(CorrectedResultCollector.java:28) ~[JMeterPlugins-Extras.jar:?]
at org.apache.jmeter.engine.StandardJMeterEngine.notifyTestListenersOfStart(StandardJMeterEngine.java:205) ~[ApacheJMeter_core.jar:5.4.1]
at org.apache.jmeter.engine.StandardJMeterEngine.run(StandardJMeterEngine.java:382) ~[ApacheJMeter_core.jar:5.4.1]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
这是因为缺少了一个jar包所致,请下载jmeter-plugins-cmn-jmeter-0.x.jar,拷贝到jmeter的lib/ext文件夹下,然后重启jmeter再试即可看到优美的CPU/MEM监控曲线;
jmeter-plugins-cmn-jmeter-0.x.jar下载地址参考:https://mvnrepository.com/artifact/kg.apc/jmeter-plugins-cmn-jmeter
https://maven.aliyun.com/repository/central/kg/apc/jmeter-plugins-cmn-jmeter/0.7/jmeter-plugins-cmn-jmeter-0.7.jar
https://maven.aliyun.com/repository/central/kg/apc/jmeter-plugins-cmn-jmeter/0.6/jmeter-plugins-cmn-jmeter-0.6.jar