背景
在使用Jmeter进行一些高并发的压测时候,请求参数重需要构造唯一的订单ID。
开始时使用了 ${__Random(100000,999999,)}
以及 __time()
的组合来生成唯一订单ID,但由于TPS较大的情况下,最终导致了出现重复订单ID😂。。。
于是梳理了下后续可能压测的场景,根据此方案制定了最终的解决方案。后续可能压测的场景如下:
- 场景一:一个线程组中存在多个线程并发生成唯一ID;
- 场景二:多个线程组 + 每个线程组中是多个线程并发生成唯一ID;
- 场景三:多个Jmeter脚本 + 多个线程组 + 每个线程组中是多个线程并发生成唯一ID;
解决方案
PS:以下方法均在 BeanShell PreProcessor
中进行验证得出的结果。
方法一: 通过 UUID()
函数生成随机字符串;
1 | String randomStr = "${__UUID}"; |
该方法简单又快速,但这种带字符串的看起来不太符合订单ID(如果仅仅是生成唯一ID,可以使用该方法)。
方法二:使用多个函数组合 (推荐)
组合的函数如下:
ctx.getThread().getThreadName()
:当前的线程组名,但大部分时候形式是:x-x,所以需要进行裁剪;${__threadNum}
:在单个线程组中的线程号,这个在单个组中是递增并且唯一的;${__counter(,)}
:计数器进行计数;Date()
:当前时间戳;(代码中使用了格式化生成年月日 时分秒毫秒的格式)
最终脚本内容如下:
1 | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
实验
但个人感觉场景三一一多个脚本同时运行时,可能会存在问题。 其 groupId
、 threadNum
、threadCount
拼接起来仍然存在会一致的情况。因为这些值并不是跨脚本唯一的。比如:groupId可能都是1, threadNum也是1,threadCount也是2。
于是做了一个试验去进行验证:
同时执行3个脚本,每个脚本存在一个线程组, 每个线程组配置的100个并发,持续5分钟看是否出现重复的订单ID。
结果:共生成了 8442274 个订单,但无重复。 当然这可能存在运气😂,这个暂时先使用该方法作为最终解决方案。