最近手上在进行一个性能测试项目,脚本是java语言使用httpClient实现http请求。并发用户数线程只有40个,但是服务器端启动的线程出现了400多个,是哪里平白无故出现这么多线程呢?肯定是有问题的,于是把线程的堆栈信息打印出来查看,发现大量的TIMED_WAITIND等待状态的线程。
"http-bio-8058-exec-210" daemon prio=10 tid=0x00007f72a805c800 nid=0x4049 waiting on condition [0x00007f729a6b6000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000780dd6cb8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2082)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:86)
at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:32)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None</span></span>
第一时间就排查了服务器端是否对线程池的使用有问题,会自动生成过多的线程,经过排查并没有使用线程池的地方,于是我们转向排查是否脚本的编写问题。
脚本代码如下:
public class Actions
{
public int init() throws Throwable {
return 0;
}//end of init
public int action() throws Throwable {
HttpClient client = new HttpClient();
String url = "http://xxxxx";
GetMethod method = new GetMethod(url);
client.executeMethod(method);
System.out.println(method.getStatusLine());
String respStr1 = method.getResponseBodyAsString();
method.releaseConnection();
return 0;
}//end of action
public int end() throws Throwable {
return 0;
}//end of end
}
</span>
这是一个最基础的http请求,我把脚本简化后,只操作一个http请求,检查对服务器端线程的影响。在发起40个用户后,线程达到了200多。可见问题就出现在了HttpClient的方法上。大部分人使用HttpClient都是使用类似上面的事