JMeter逻辑控制器可以对元件的执行逻辑进行控制,就像编程一样,实现业务需求。
JMeter包括了以下逻辑控制器:
![image-20210602125702490](https://i-blog.csdnimg.cn/blog_migrate/930493e82c61ad2bb37e98f94c4851d9.png)
一共17种。除了仅一次控制器外,其他控制器下可以嵌套别的种类的逻辑控制器。
If Controller
![image-20210603114905093](https://i-blog.csdnimg.cn/blog_migrate/cef6c5b35f0c2c129589a47992ce4240.png)
控制此节点下的元件是否运行。
Expression:可以使用变量表达式或JavaScript。
勾选Interpret Condition as Variable Expression表示使用变量表达式,建议勾选上。
Use status of last Sample表示判断上个取样器是否成功,点击后会把${JMeterThread.last_sample_ok}
添加到Expression输入框中:
![image-20210603123813310](https://i-blog.csdnimg.cn/blog_migrate/ce3b93be60db0c16fe3a6d3a938cc07d.png)
Evaluate for all children:判断条件是否针对所有的子节点,默认不勾选,只在If Controller入口处判断一次,否则每次节点都会进行判断。
Transaction Controller
![image-20210603130929785](https://i-blog.csdnimg.cn/blog_migrate/1ef2bf42115ef1be86daa4d5366d7a23.png)
事务控制器能够帮我们把一堆请求归到一个大的事务中去,在报告分析时更方便。
Generate parent sample:是否生成父取样结果,勾选后有两个效果,一是Aggregate Report会看到Transaction Controller字样,它把节点下的取样器的运行结果(如消耗时间)累加在一起(注意事务控制器下如果有多个取样器,全部取样器都运行成功,整个事务控制器才算成功),比如:
![image-20210603134736994](https://i-blog.csdnimg.cn/blog_migrate/f91f0d0d4db789aa707a19d1464789ce.png)
二是View Return Tree中会看到多一个结果,比如:
![image-20210603134903626](https://i-blog.csdnimg.cn/blog_migrate/134b455b8b750071001e7550881c979a.png)
Include duration of timer and pre-post processors in generated sample:包括定时器和前置-后置处理器的耗时,建议不用勾选,不然会影响统计结果。
Loop Controller
![image-20210603130439893](https://i-blog.csdnimg.cn/blog_migrate/717b92dc495840e33a482226b0ffe49d.png)
跟线程组的Loop设置一样。最终执行次数 = 线程组执行次数 x 循环控制器执行次数,比如线程组设置3次,循环控制器设置6次,那么控制器下面的元件会执行18次。
While Controller
![image-20210603102158130](https://i-blog.csdnimg.cn/blog_migrate/37934ca126488598d8d4e888d7659c25.png)
其子节点下的元件将一直运行直到While条件为false。
Condition:接受变量表达式与变量,比如${inputVar}<10
,当inputVar=7时,它的子节点将一直运行下去。
另外提供以下三个常量:
- Blank:当循环中有取样器失败后停止。
- LAST:当循环前有取样器失败则不进入循环。
- Otherwise:当判断条件为false时停止循环。
Critical Section Controller
![image-20210603135042953](https://i-blog.csdnimg.cn/blog_migrate/ab8d4dd6248ace5005a673f0ac4c2a3e.png)
加锁让多线程顺序执行。
比如,不加锁,3个线程是并行执行的。:
![image-20210603135645383](https://i-blog.csdnimg.cn/blog_migrate/b02417f3b47d99271ae5a8aa837d7d07.png)
加锁以后,变成顺序执行了:
![image-20210603135756370](https://i-blog.csdnimg.cn/blog_migrate/6adf11da7540fc3dbf21ddb4e0949620.png)
ForEach Controller
![image-20210602161433143](https://i-blog.csdnimg.cn/blog_migrate/52cd32fcaa6abff3dd9c699090ced10f.png)
Input variable prefix:输入变量前缀。可以是用户自定义变量里面的多个变量如id_1, id_2, id_3(这里就填写id
):
![image-20210602162923818](https://i-blog.csdnimg.cn/blog_migrate/21450ae77ae3fc5a5320ce9220f7a068.png)
也可以是正则表达式提取器匹配到的多个值(这里就填写varName
):
![image-20210602163146363](https://i-blog.csdnimg.cn/blog_migrate/03d59edd0ea3418e1472a24868447f5c.png)
Start index for loop (exclusive):循环变量下标起点(不包括自己)。
End index for loop (inclusive):循环变量下标终点(包括自己)。
Output variable name:输出变量名,比如returnVar,通过${returnVar}
引用。
Add "_"
before number:变量前缀后是否加“_”
作为分隔符。
示例:
![image-20210602171152862](https://i-blog.csdnimg.cn/blog_migrate/2a80d24548acf85d3028270d6e54792c.png)
![image-20210602163814127](https://i-blog.csdnimg.cn/blog_migrate/12fb3c5d8ddd42eb0a60e9cd2ca88371.png)
Include Controller
![image-20210602170315590](https://i-blog.csdnimg.cn/blog_migrate/7f2d8a5bbda29f09325dd99c5dabf8a4.png)
类似于程序中的函数,可以把其他.jmx
文件包含进来。
被导入的测试计划有特殊要求:不能有线程组,只能包含简单控制器及控制器下的元件。
比如一个查询订单的业务操作用Sampler来模拟,然后放到简单控制器中作为一个执行单元,别的地方也要用到时,就可以不重写直接引用过来。
Interleave Controller
其节点下的取样器会交替执行。
![image-20210603103110338](https://i-blog.csdnimg.cn/blog_migrate/10cad6d724a02eba2d8a8b86a1c93f6b.png)
比如:
![image-20210603104449388](https://i-blog.csdnimg.cn/blog_migrate/1bf218a7704d94eb57dd05327343a834.png)
1个线程迭代3次,执行顺序是1 3, 2 3, 1 3。
Ignore sub-controller blocks:不执行子控制器,只执行当前这个交替控制器。比如:
![image-20210603104638689](https://i-blog.csdnimg.cn/blog_migrate/6415232a25aa3470dfcf0d4945f48005.png)
1个线程迭代4次,执行顺序是1, 2, 3, 1,Loop Controller失效。注意,1 2 3是交替执行的,每次迭代只执行其中一个。(如果不勾选,Loop设置为2,那么执行顺序是:1, 2, 3 3, 1)
嵌套的例子:
![image-20210603105406784](https://i-blog.csdnimg.cn/blog_migrate/043a829c6ba19363671213e7f0fbae73.png)
1个线程迭代5次,执行顺序是:1, 3, 2, 4, 1。
Interleave across threads:跨线程交替运行。比如:
![image-20210603110016555](https://i-blog.csdnimg.cn/blog_migrate/2e32b76c4707a5f781f4694db84b5a0d.png)
3个线程2次迭代,不勾选的执行顺序:1 2, 1 2, 1 2;勾选的执行顺序:1 2, 2 3, 3 4。
Once Only Controller
![image-20210603110413542](https://i-blog.csdnimg.cn/blog_migrate/e77ce121281fb5efc17bf46b109e590c.png)
其子元件只运行一次。比如只登录一次,只读取一次CSV,只连一次数据库。
注意,子节点放个CSV Data Set Config,可以让每个线程只读一次,然后使用同一条数据进行反复请求。
多个线程是一行一行取值的,不会重复。
比如:
![image-20210603144054471](https://i-blog.csdnimg.cn/blog_migrate/a4667a611af063863d9062767e3a4a15.png)
2个线程3次迭代,那么:
- 线程a只读一次,取到尾号1845这条数据,然后用这条数据迭代请求3次。
- 线程b只读一次,取到尾号0740这条数据,然后用这条数据迭代请求3次。
Random Controller
![image-20210603130054682](https://i-blog.csdnimg.cn/blog_migrate/ecd8ee97e35ec14a9064605010ad33d6.png)
节点下的元件随机运行,运行顺序不定。
Ignore sub-controller blocks:不执行子控制器,只执行当前这个交替控制器。
Random Order Controller
![image-20210603130320773](https://i-blog.csdnimg.cn/blog_migrate/f252c4e11392dc9e458b5b2044532375.png)
节点下的元件随机执行,且每个元件只执行一次。
Recording Controller
![image-20210603130826176](https://i-blog.csdnimg.cn/blog_migrate/a067993571a8dc6a8b3a8075c650e51c.png)
没用。
Runtime Controller
![image-20210602171326855](https://i-blog.csdnimg.cn/blog_migrate/a9e3556b3c3afe7870c13e552a92b2df.png)
用来控制其子元件的执行时长。
Runtime单位为秒,默认为1,去掉1或者设置为0,它的子元件不执行。
Simple Controller
![image-20210602165143999](https://i-blog.csdnimg.cn/blog_migrate/d06446860e9d64af454a837a0813eeb9.png)
简单控制器很简单,就是用来给Sampler分组的。它指定了一个执行单元,不会改变元件的执行顺序。
示例:
![image-20210602170154775](https://i-blog.csdnimg.cn/blog_migrate/6c508d919d78061ac59bd0a31f461ca3.png)
Throughput Controller
![image-20210603112810046](https://i-blog.csdnimg.cn/blog_migrate/b21ab8a2c6f63613ecb09f2c4bd42439.png)
控制子元件的执行次数(不能控制吞吐量,想控制吞吐量可以使用Constant Throughput Timer)。
Percent Executions:按执行次数的百分比来计算控制的执行次数,此时Throughput取值是0~100。
Total Executions:按Throughput的值来指定执行次数。
Per User:只对Total Executions生效,勾选后每个线程单独计算,不勾选则所有线程加起来计算。比如2个线程,每个线程迭代10次,Throughput值为6,,勾选Per User则分别计算分别执行6次共12次;不勾选Per User则加起来计算,共执行6次。
Module Controller
![image-20210603125248483](https://i-blog.csdnimg.cn/blog_migrate/043f71e9dae1b645408a9a3de5ec1ac8.png)
在当前测试计划中引入新的测试片段,测试片段由控制器、取样器及辅助元件构成,能够完成负载的模拟。
示例:
![image-20210603125605964](https://i-blog.csdnimg.cn/blog_migrate/a8ecc375ab84b21bf79b34c988f54336.png)
把测试片段里面的Loop Controller引了进来。
Module To Run:下拉列表,选择引入哪一个脚本片段(既包括测试片段也包括当前测试计划的控制器)。
Switch Controller
![image-20210602171831079](https://i-blog.csdnimg.cn/blog_migrate/4582a052e97677821f06555ac122c3af.png)
类似于高级语言中的Switch逻辑控制语句。
Switch Value:可以为数字,匹配取样器编号(子节点中取样器编号从0开始),不指定或指定编号超出了子节点数,则运行第0个取样器;也可以为字符,匹配取样器名称,匹配不上就会默认查找名称为default的取样器,如果没有则不运行。
小结
本文对JMeter所有控制器进行了介绍,从这些控制器能感受到JMeter之所以这么流行,是因为它实在太成熟了,这里面的技术需要多少沉淀才能做得出来呀。有时间一定得看看JMeter的源码深度学习下。
参考资料:
《全栈性能测试修炼宝典JMeter实战》