__counter是JMeter 中一个内置的、线程安全的计数函数。它每次被调用时,都会根据一个内部计数器生成一个递增的数字,一般从 1 开始,每次增加 1。
作用是为测试提供唯一的、递增的序号。在性能测试中,这个特性让 __counter 函数在生成唯一ID、控制业务流量比例、参数化数据以及标记迭代次数等场景下,变得尤为实用。
函数参数详解
__counter 函数支持传入两个参数,用来控制计数器的行为。
第一个参数:计数方式
这是一个布尔值(TRUE 或 FALSE),用于决定计数器的独立或共享。
TRUE(独立方式):为每个线程(模拟用户) 维护一个独立的计数器。线程间互不干扰,每个线程都从 1 开始计数,适合用于记录单个用户的“第几次操作”。
FALSE(全局方式):所有线程共享一个全局计数器。一个线程调用后,计数器的值会自增,下一个调用的线程会得到最新的值,适合用于为所有请求生成全局唯一的序号。
第二个参数:变量名
这是一个可选参数。如果设置了该参数,计数器的当前值会被同步保存到一个 JMeter 变量中,方便在脚本的其他地方通过 ${变量名} 的形式重复引用同一个值。
基础语法和使用示例
1. 语法格式
jmeter
${__counter(独立方式, 变量名)}
2. 实用示例
生成全局唯一序号:
使用全局方式,且不指定变量名。这是 __counter 最简洁的用法。
jmeter
${__counter(FALSE,)}
情形:在 HTTP 请求中为订单号、交易流水号等参数生成一个全局唯一的序列。如果启动了 10 个线程,循环 5 次,那么你将得到从 1 到 50 的一系列连续不重复的序号。
为每个用户标记独立的操作次数:
使用独立方式,并将值存入变量,方便脚本其他地方引用。
jmeter
${__counter(TRUE, userActionCount)}
情形:需要在一个线程组的多个取样器中,标记这是该用户的第几次操作。你可以在第一个请求中调用此函数,然后在后续的请求或日志中引用 ${userActionCount} 来获取同一个值。
动态生成批量测试数据
可以和 JMeter 的 __V 函数配合,实现变量的动态拼接,从而批量获取变量值。
jmeter
${__V(user_${__counter(,)},)}
情形:设定义了 user_1, user_2, ..., user_10 等一组变量。通过上述嵌套,每次循环调用都会动态拼接并获取 user_1, user_2 ... 的值,极大地方便了批量数据测试。
精细化控制业务流量比例
借助数学运算(如取模 %)和思路控制器(如 If Controller),可以精确控制不同业务请求的执行比例。
jmeter
${__counter(TRUE,)}%5==0
情形:在 If Controller 的条件表达式中使用。这个表达式代表每执行 5 次操作,才会触发一次控制器内的请求。可以用来模拟“浏览:购买 = 4:1”的流量比例模型。
常见问题和实践
一个已知的 Bug:计数器从 2 开始递增
在 JMeter 5.6.3 等较新版本中,部分用户会遇到 __counter 函数输出 2, 4, 6... 等偶数序列的问题。
解决方法:编辑 JMeter 安装目录下 bin 文件夹中的 jmeter.properties 文件,找到 function.cache.per.iteration 这一行(默认可能被注释),取消注释并将其值修改为 true,保存后重启 JMeter 即可解决。
和计数器(Counter)配置元件的区别
很多人会将 __counter 函数和 JMeter 的“计数器”(Counter)配置元件混淆,但它们有本质区别。
归属类型不同:__counter 是一个函数,可以直接嵌入到任何参数或字段中使用;而“计数器”是一个配置元件,需要作为独立的组件添加到测试计划中。
计数灵活性不同:__counter 的计数规则是固定的,始终从 1 开始,每次递增 1,无法修改;而“计数器”元件则灵活得多,你可以自由设定它的起始值、递增值(步长),以及最大值。
数字格式化能力不同:__counter 输出的就是纯粹的数字,不支持任何格式化;如果你需要像 var_001 这样带固定位数和前缀的编号,“计数器”元件可以轻松做到,它专门提供了格式化输出的选项。
线程安全实现方式不同:__counter 原生支持线程安全,直接通过第一个参数(TRUE 或 FALSE)就能在独立方式和全局方式间切换;而“计数器”元件则需要通过勾选“和每用户独立的跟踪计数器”等选项来保证线程安全。
适用场景不同:当你的需求很简单,只想快速获得一个自增的编号时,__counter 函数是最直接、最轻量的选择;但如果你的情形很复杂,比如需要从一个特定的值开始计数、按某个步长递增,或者生成格式化的编号,就应该选用功能更强大的“计数器”配置元件。