【原创】Jmeter实战 - 实用手册
编写此文,主要想通过这种方式,记录自己研究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">falseboolProp> 7 <boolProp name="TestPlan.tearDown_on_shutdown">trueboolProp> 8 <boolProp name="TestPlan.serialize_threadgroups">falseboolProp> 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">8888stringProp> 17 <collectionProp name="ProxyControlGui.exclude_list"/> 18 <collectionProp name="ProxyControlGui.include_list"/> 19 <boolProp name="ProxyControlGui.capture_http_headers">trueboolProp> 20 <intProp name="ProxyControlGui.grouping_mode">0intProp> 21 <boolProp name="ProxyControlGui.add_assertion">falseboolProp> 22 <stringProp name="ProxyControlGui.sampler_type_name">stringProp> 23 <boolProp name="ProxyControlGui.sampler_redirect_automatically">falseboolProp> 24 <boolProp name="ProxyControlGui.sampler_follow_redirects">trueboolProp> 25 <boolProp name="ProxyControlGui.use_keepalive">trueboolProp> 26 <boolProp name="ProxyControlGui.detect_graphql_request">trueboolProp> 27 <boolProp name="ProxyControlGui.sampler_download_images">falseboolProp> 28 <intProp name="ProxyControlGui.proxy_http_sampler_naming_mode">0intProp> 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">falseboolProp> 33 <boolProp name="ProxyControlGui.regex_match">falseboolProp> 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">continuestringProp> 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">MstringProp> 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">falseboolProp> 57 <boolProp name="CookieManager.controlledByThreadGroup">falseboolProp> 58 CookieManager> 59 <hashTree/> 60 <TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="001_Login" enabled="true"> 61 <boolProp name="TransactionController.includeTimers">falseboolProp> 62 <boolProp name="TransactionController.parent">falseboolProp> 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">GETstringProp> 75 <boolProp name="HTTPSampler.follow_redirects">trueboolProp> 76 <boolProp name="HTTPSampler.auto_redirects">falseboolProp> 77 <boolProp name="HTTPSampler.use_keepalive">trueboolProp> 78 <boolProp name="HTTPSampler.DO_MULTIPART_POST">falseboolProp> 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">falsestringProp> 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">falseboolProp> 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">falsestringProp> 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">truestringProp> 111 <stringProp name="filename">stringProp> 112 <stringProp name="parameters">stringProp> 113 <stringProp name="script">stringProp> 114 <stringProp name="scriptLanguage">groovystringProp> 115 JSR223PostProcessor> 116 <hashTree/> 117 hashTree> 118 <DebugSampler guiclass="TestBeanGUI" testclass="DebugSampler" testname="Debug Sampler" enabled="true"> 119 <boolProp name="displayJMeterProperties">falseboolProp> 120 <boolProp name="displayJMeterVariables">trueboolProp> 121 <boolProp name="displaySystemProperties">falseboolProp> 122 DebugSampler> 123 <hashTree/> 124 hashTree> 125 <TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="002_TestCase_01" enabled="true"> 126 <boolProp name="TransactionController.includeTimers">falseboolProp> 127 <boolProp name="TransactionController.parent">falseboolProp> 128 TransactionController> 129 <hashTree/> 130 hashTree> 131 <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true"> 132 <boolProp name="ResultCollector.error_logging">falseboolProp> 133 <objProp> 134 <name>saveConfigname> 135 <value class="SampleSaveConfiguration"> 136 <time>truetime> 137 <latency>truelatency> 138 <timestamp>truetimestamp> 139 <success>truesuccess> 140 <label>truelabel> 141 <code>truecode> 142 <message>truemessage> 143 <threadName>truethreadName> 144 <dataType>truedataType> 145 <encoding>falseencoding> 146 <assertions>trueassertions> 147 <subresults>truesubresults> 148 <responseData>falseresponseData> 149 <samplerData>falsesamplerData> 150 <xml>falsexml> 151 <fieldNames>truefieldNames> 152 <responseHeaders>falseresponseHeaders> 153 <requestHeaders>falserequestHeaders> 154 <responseDataOnError>falseresponseDataOnError> 155 <saveAssertionResultsFailureMessage>truesaveAssertionResultsFailureMessage> 156 <assertionsResultsToSave>0assertionsResultsToSave> 157 <bytes>truebytes> 158 <sentBytes>truesentBytes> 159 <url>trueurl> 160 <threadCounts>truethreadCounts> 161 <idleTime>trueidleTime> 162 <connectTime>trueconnectTime> 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">falseboolProp> 170 <objProp> 171 <name>saveConfigname> 172 <value class="SampleSaveConfiguration"> 173 <time>truetime> 174 <latency>truelatency> 175 <timestamp>truetimestamp> 176 <success>truesuccess> 177 <label>truelabel> 178 <code>truecode> 179 <message>truemessage> 180 <threadName>truethreadName> 181 <dataType>truedataType> 182 <encoding>falseencoding> 183 <assertions>trueassertions> 184 <subresults>truesubresults> 185 <responseData>falseresponseData> 186 <samplerData>falsesamplerData> 187 <xml>falsexml> 188 <fieldNames>truefieldNames> 189 <responseHeaders>falseresponseHeaders> 190 <requestHeaders>falserequestHeaders> 191 <responseDataOnError>falseresponseDataOnError> 192 <saveAssertionResultsFailureMessage>truesaveAssertionResultsFailureMessage> 193 <assertionsResultsToSave>0assertionsResultsToSave> 194 <bytes>truebytes> 195 <sentBytes>truesentBytes> 196 <url>trueurl> 197 <threadCounts>truethreadCounts> 198 <idleTime>trueidleTime> 199 <connectTime>trueconnectTime> 200 value> 201 objProp> 202 <stringProp name="filename">stringProp> 203 <longProp name="interval_grouping">1000longProp> 204 <boolProp name="graph_aggregated">falseboolProp> 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">falseboolProp> 210 <boolProp name="exclude_checkbox_state">falseboolProp> 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">falseboolProp> 215 <objProp> 216 <name>saveConfigname> 217 <value class="SampleSaveConfiguration"> 218 <time>truetime> 219 <latency>truelatency> 220 <timestamp>truetimestamp> 221 <success>truesuccess> 222 <label>truelabel> 223 <code>truecode> 224 <message>truemessage> 225 <threadName>truethreadName> 226 <dataType>truedataType> 227 <encoding>falseencoding> 228 <assertions>trueassertions> 229 <subresults>truesubresults> 230 <responseData>falseresponseData> 231 <samplerData>falsesamplerData> 232 <xml>falsexml> 233 <fieldNames>truefieldNames> 234 <responseHeaders>falseresponseHeaders> 235 <requestHeaders>falserequestHeaders> 236 <responseDataOnError>falseresponseDataOnError> 237 <saveAssertionResultsFailureMessage>truesaveAssertionResultsFailureMessage> 238 <assertionsResultsToSave>0assertionsResultsToSave> 239 <bytes>truebytes> 240 <sentBytes>truesentBytes> 241 <url>trueurl> 242 <threadCounts>truethreadCounts> 243 <idleTime>trueidleTime> 244 <connectTime>trueconnectTime> 245 value> 246 objProp> 247 <stringProp name="filename">stringProp> 248 <longProp name="interval_grouping">500longProp> 249 <boolProp name="graph_aggregated">falseboolProp> 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">falseboolProp> 255 <boolProp name="exclude_checkbox_state">falseboolProp> 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">falseboolProp> 260 <objProp> 261 <name>saveConfigname> 262 <value class="SampleSaveConfiguration"> 263 <time>truetime> 264 <latency>truelatency> 265 <timestamp>truetimestamp> 266 <success>truesuccess> 267 <label>truelabel> 268 <code>truecode> 269 <message>truemessage> 270 <threadName>truethreadName> 271 <dataType>truedataType> 272 <encoding>falseencoding> 273 <assertions>trueassertions> 274 <subresults>truesubresults> 275 <responseData>falseresponseData> 276 <samplerData>falsesamplerData> 277 <xml>falsexml> 278 <fieldNames>truefieldNames> 279 <responseHeaders>falseresponseHeaders> 280 <requestHeaders>falserequestHeaders> 281 <responseDataOnError>falseresponseDataOnError> 282 <saveAssertionResultsFailureMessage>truesaveAssertionResultsFailureMessage> 283 <assertionsResultsToSave>0assertionsResultsToSave> 284 <bytes>truebytes> 285 <sentBytes>truesentBytes> 286 <url>trueurl> 287 <threadCounts>truethreadCounts> 288 <idleTime>trueidleTime> 289 <connectTime>trueconnectTime> 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:
第九步:命令行方式执行测试,并察看执行完成的报告结果数据;参考
第十步:需要分布式执行大批量测试,参考
第十一步:由了RT和TPS,还差CPU与MEM监控,
Linux/Unix请参考nmon监控方法
当然也可以用Jmeter提供的监控方法,参考,如果遇到了监控问题,请参考接下来的 ※ 划重点 ※
细节的参考,给两个地址,一个是官方文档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