0%

Jmeter唯一ID

背景

​ 在使用Jmeter进行一些高并发的压测时候,请求参数重需要构造唯一的订单ID。

​ 开始时使用了 ${__Random(100000,999999,)} 以及 __time() 的组合来生成唯一订单ID,但由于TPS较大的情况下,最终导致了出现重复订单ID😂。。。

于是梳理了下后续可能压测的场景,根据此方案制定了最终的解决方案。后续可能压测的场景如下:

  • 场景一:一个线程组中存在多个线程并发生成唯一ID;
  • 场景二:多个线程组 + 每个线程组中是多个线程并发生成唯一ID;
  • 场景三:多个Jmeter脚本 + 多个线程组 + 每个线程组中是多个线程并发生成唯一ID;

解决方案

PS:以下方法均在 BeanShell PreProcessor 中进行验证得出的结果。

方法一: 通过 UUID() 函数生成随机字符串;

1
2
3
4
5
String randomStr = "${__UUID}";
log.info("test: " + randomStr);

# 日志打印如下:
2021-12-16 18:07:52,667 INFO o.a.j.u.BeanShellTestElement: test: 863a7d5a-2487-4cba-ad9d-2b159487019b

该方法简单又快速,但这种带字符串的看起来不太符合订单ID(如果仅仅是生成唯一ID,可以使用该方法)。

方法二:使用多个函数组合 (推荐)

组合的函数如下:

  • ctx.getThread().getThreadName():当前的线程组名,但大部分时候形式是:x-x,所以需要进行裁剪;

  • ${__threadNum}:在单个线程组中的线程号,这个在单个组中是递增并且唯一的;

  • ${__counter(,)}:计数器进行计数;

  • Date() :当前时间戳;(代码中使用了格式化生成年月日 时分秒毫秒的格式)

最终脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String groupId = ((ctx.getThread().getThreadName().toString()).split(" ")[1]).split("-")[0];
Integer threadNum = ${__threadNum};
Integer threadCount = ${__counter(,)};
String randomNumStr = String.valueOf(threadNum) + String.valueOf(threadCount) + groupId;
String orderId = sdf.format(new Date()) + randomNumStr ;
log.info("test groupId: " + groupId);
log.info("test threadNum: " + threadNum);
log.info("test threadCount: " + threadCount);
log.info("test randomNumStr: " + randomNumStr);
log.info("test orderId: " + orderId);

2021-12-16 19:02:08,259 INFO o.a.j.u.BeanShellTestElement: test groupId: 1
2021-12-16 19:02:08,259 INFO o.a.j.u.BeanShellTestElement: test threadNum: 1
2021-12-16 19:02:08,259 INFO o.a.j.u.BeanShellTestElement: test threadCount: 2
2021-12-16 19:02:08,259 INFO o.a.j.u.BeanShellTestElement: test randomNumStr: 121
2021-12-16 19:02:08,260 INFO o.a.j.u.BeanShellTestElement: test orderId: 20211216190208259121

实验

​ 但个人感觉场景三一一多个脚本同时运行时,可能会存在问题。 其 groupIdthreadNumthreadCount 拼接起来仍然存在会一致的情况。因为这些值并不是跨脚本唯一的。比如:groupId可能都是1, threadNum也是1,threadCount也是2。

于是做了一个试验去进行验证:

同时执行3个脚本,每个脚本存在一个线程组, 每个线程组配置的100个并发,持续5分钟看是否出现重复的订单ID。

结果:共生成了 8442274 个订单,但无重复。 当然这可能存在运气😂,这个暂时先使用该方法作为最终解决方案。

------------- 本 文 结 束 感 谢 您 的 阅 读 -------------