日常开发比较多与第三方服务通过HTTP接口对接,但是为了保证服务不会因为请求资源过度消耗而使服务宕机,那么我们往往会引入线程池,我原先在开发过程中给同事封装了一套http线程池服务,是基于PoolingHttpClientConnectionManager的,原本就有考虑将资源释放,直到今天才发现原来服务一直都有问题,资源无法释放一直占用着资源,直到把连接达到最大连接数服务就不断出现获取连接超时异常。
先贴一下原先的部分代码:
PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager();
clientConnectionManager.setMaxTotal(maxTotal);
clientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
// 启动回收资源线程
new ReleaseConnectionThread(clientConnectionManager).start();
public class ReleaseConnectionThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
public ReleaseConnectionThread(HttpClientConnectionManager connMgr) {
this.connMgr = connMgr;
this.shutdown = false;
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
// 等待2秒
wait(2000);
// 关闭失效连接
connMgr.closeExpiredConnections();
//关闭空闲超过5秒的连接
connMgr.closeIdleConnections(5000, TimeUnit.MILLISECONDS);
}
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
这里有一个注意点,就是当http请求有响应内容的时候:
HttpEntity entity = httpresponse.getEntity();
是一直占用着资源的,而资源回收资源线程是将空闲的、失效的连接回收,所以我们需要手动去关闭资源占用:
EntityUtils.consume(entity);
在处理完响应内容后主动调用就行啦!
果真重启服务能解决很多问题,但也隐藏了很多问题...