【原创】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">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

posted @ 2022-01-20 22:52  田超  阅读(2283)  评论(0编辑  收藏  举报