当前位置 : 主页 > 编程语言 > java >

Jmeter Arrivals Thread Group测试计划无法正常终止问题解决

来源:互联网 收集:自由互联 发布时间:2023-09-03
序 在做压测的过程中,发现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中。

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

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

// 当前不需要这么多活跃线程,把活跃线程放入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,问题消失。

网友评论