Jmeter Arrivals Thread Group测试计划如何彻底解决无法正常终止的难题?

2026-04-19 12:161阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计763个文字,预计阅读时间需要4分钟。

Jmeter Arrivals Thread Group测试计划如何彻底解决无法正常终止的难题?

序号+在进行压测的过程中,发现Jmeter的Arrivals Thread Group(以下简称ATG)这个线程组会存在一个问题,即在完成测试目标后,Running Thread不会降为0,测试计划不会正常结束。网上搜索了一通,发现一个常见的方法:

在做压测的过程中,发现Jmeter的Arrivals Thread Group(后文以ATG指代)这个线程组会有一个问题,就是在完成测试目标以后,Running Thread不会降为0,测试计划不会正常终止。网上搜索一通,居然都没有搜到谁提出这个问题。还好这个项目是开源的,我们都是程序员,有代码就不怕解决不了。


ATG简单说明

ATG是以QPS为目标的压测方法,在指定了目标QPS以后,ATG会根据请求的响应时间,自动调整线程数去尽量维持压测期间的QPS,这种行为就非常类似我们服务端到服务端的调用行为。另外提一句,Open Model Thread Group也可以达到类似的效果,但是本人在使用OMTG的过程中发现解决不了长连接的问题,所以最终还是选用ATG。


修复过程

ATG的源代码在jmeter-plugin这个项目中,主要的类是ArrivalsThreadGroup,阅读代码会发现此类有一个poolThreads的成员,是Set类型。这很好理解,因为ATG要不断的调整活跃的线程数,设计一个线程池来避免频繁的创建销毁线程是很必要的。同时ArrivalsThreadGroup的父类中还定义了一个threads的成员,这个成员保存的就是当前活跃的线程。

在压测过程中,当ATG发现压测目标响应慢了,需要更多的活跃线程,就会尝试从poolThreads取出一个线程放入threads,反之亦然。一个线程不应该同时存在在poolThreads和threads中。

Jmeter Arrivals Thread Group测试计划如何彻底解决无法正常终止的难题?

...此处省去的调试过程...

最终我们会留意到如下两个方法。

// 当前不需要这么多活跃线程,把活跃线程放入poolThreads public boolean movedToPool(DynamicThread thread) { threads.remove(thread); ...省略代码... poolThreads.add(thread); ...省略代码... synchronized (thread) { try { thread.wait(); } catch (InterruptedException e) { log.debug("Interrupted", e); } } } // 需要更多活跃线程,把活跃线程加入threads public synchronized boolean releasedPoolThread() { ...省略代码... poolThreads.remove(thread); threads.add(thread); ...省略代码... synchronized (thread) { thread.notify(); } }

看到这个代码问题就很明显了,这样针对poolThreads和threads的操作在多线程环境下就有概率发生不一致的问题,导致一个线程同时存在在poolThreads和threads中。这样会导致活跃线程无法被成功释放,从而导致测试计划无法停止。修复方法也很粗暴,将针对poolThreads和threads的操作也放入到同步代码中就好了。修改代码如下

// 当前不需要这么多活跃线程,把活跃线程放入poolThreads public boolean movedToPool(DynamicThread thread) { synchronized (thread) { threads.remove(thread); ...省略代码... poolThreads.add(thread); ...省略代码... try { thread.wait(); } catch (InterruptedException e) { log.debug("Interrupted", e); } } } // 需要更多活跃线程,把活跃线程加入threads public synchronized boolean releasedPoolThread() { synchronized (thread) { ...省略代码... poolThreads.remove(thread); threads.add(thread); ...省略代码... thread.notify(); } }

重新构建替换原来的jmeter-plugins-casutg-2.10.jar,问题消失。

本文共计763个文字,预计阅读时间需要4分钟。

Jmeter Arrivals Thread Group测试计划如何彻底解决无法正常终止的难题?

序号+在进行压测的过程中,发现Jmeter的Arrivals Thread Group(以下简称ATG)这个线程组会存在一个问题,即在完成测试目标后,Running Thread不会降为0,测试计划不会正常结束。网上搜索了一通,发现一个常见的方法:

在做压测的过程中,发现Jmeter的Arrivals Thread Group(后文以ATG指代)这个线程组会有一个问题,就是在完成测试目标以后,Running Thread不会降为0,测试计划不会正常终止。网上搜索一通,居然都没有搜到谁提出这个问题。还好这个项目是开源的,我们都是程序员,有代码就不怕解决不了。


ATG简单说明

ATG是以QPS为目标的压测方法,在指定了目标QPS以后,ATG会根据请求的响应时间,自动调整线程数去尽量维持压测期间的QPS,这种行为就非常类似我们服务端到服务端的调用行为。另外提一句,Open Model Thread Group也可以达到类似的效果,但是本人在使用OMTG的过程中发现解决不了长连接的问题,所以最终还是选用ATG。


修复过程

ATG的源代码在jmeter-plugin这个项目中,主要的类是ArrivalsThreadGroup,阅读代码会发现此类有一个poolThreads的成员,是Set类型。这很好理解,因为ATG要不断的调整活跃的线程数,设计一个线程池来避免频繁的创建销毁线程是很必要的。同时ArrivalsThreadGroup的父类中还定义了一个threads的成员,这个成员保存的就是当前活跃的线程。

在压测过程中,当ATG发现压测目标响应慢了,需要更多的活跃线程,就会尝试从poolThreads取出一个线程放入threads,反之亦然。一个线程不应该同时存在在poolThreads和threads中。

Jmeter Arrivals Thread Group测试计划如何彻底解决无法正常终止的难题?

...此处省去的调试过程...

最终我们会留意到如下两个方法。

// 当前不需要这么多活跃线程,把活跃线程放入poolThreads public boolean movedToPool(DynamicThread thread) { threads.remove(thread); ...省略代码... poolThreads.add(thread); ...省略代码... synchronized (thread) { try { thread.wait(); } catch (InterruptedException e) { log.debug("Interrupted", e); } } } // 需要更多活跃线程,把活跃线程加入threads public synchronized boolean releasedPoolThread() { ...省略代码... poolThreads.remove(thread); threads.add(thread); ...省略代码... synchronized (thread) { thread.notify(); } }

看到这个代码问题就很明显了,这样针对poolThreads和threads的操作在多线程环境下就有概率发生不一致的问题,导致一个线程同时存在在poolThreads和threads中。这样会导致活跃线程无法被成功释放,从而导致测试计划无法停止。修复方法也很粗暴,将针对poolThreads和threads的操作也放入到同步代码中就好了。修改代码如下

// 当前不需要这么多活跃线程,把活跃线程放入poolThreads public boolean movedToPool(DynamicThread thread) { synchronized (thread) { threads.remove(thread); ...省略代码... poolThreads.add(thread); ...省略代码... try { thread.wait(); } catch (InterruptedException e) { log.debug("Interrupted", e); } } } // 需要更多活跃线程,把活跃线程加入threads public synchronized boolean releasedPoolThread() { synchronized (thread) { ...省略代码... poolThreads.remove(thread); threads.add(thread); ...省略代码... thread.notify(); } }

重新构建替换原来的jmeter-plugins-casutg-2.10.jar,问题消失。