HttpClient引发的线程数过多导致应用崩溃

[背景]
应用中线程数量 一直在增加,dump线程日志发现大量IdleConnectionEvictor日志。在这里插入图片描述
源码分析:

    //evictExpiredConnections  这个配置作用:
				//设置一个定时线程,定时清理闲置连接,可以将这个定时时间设置为 keep alive timeout 时间的一半以保证超时前回收
                //所以在build httpclinet 的时候可以设置evictExpiredConnections()
              
            if (evictExpiredConnections || evictIdleConnections) {
              //这里要看IdleConnectionEvictor源码,里面会创建一个线程
                final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,
                        maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,
                        maxIdleTime, maxIdleTimeUnit);
                closeablesCopy.add(new Closeable() {

                    @Override
                    public void close() throws IOException {
                        connectionEvictor.shutdown();
                        try {
                            connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);
                        } catch (final InterruptedException interrupted) {
                            Thread.currentThread().interrupt();
                        }
                    }

                });
                connectionEvictor.start();//这里会创建evaictor线程
            }

所以每创建一个httpclient就会创建一个evictor线程,如果不设置连接超时时间和空闲线程回收的话这些线程会一直存在;
解决方法:
创建httpClient连接池,自定义connectManager

public class HttpClientFactory {
    private CloseableHttpClient httpClient;

    public void  construct(){
        RequestConfig config = RequestConfig.custom()
                .setSocketTimeout(10000)//请求获取数据的超时时间(即响应时间),单位毫秒
                .setConnectTimeout(10000)//设置连接超时时间,单位毫秒
                .setConnectionRequestTimeout(500)//设置从connect Manager(连接池)获取Connection 超时时间,单位毫秒
                .build();

        //设置连接存活时间,总的最大连接数和每个路由的最大连接数
        PoolingHttpClientConnectionManager poolHttpConnManager = new PoolingHttpClientConnectionManager(60, TimeUnit.SECONDS);
        poolHttpConnManager.setMaxTotal(60);
        poolHttpConnManager.setDefaultMaxPerRoute(20);

        //初始化client
        HttpClientBuilder httpBuilder = HttpClients.custom()
                .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                .setDefaultRequestConfig(config)
                .setConnectionManager(poolHttpConnManager)
                .evictExpiredConnections() 
                //MaxIdleTime 必须小于服务端的关闭时间否则有可能出现NoHttpResponse
                .evictIdleConnections(5,TimeUnit.SECONDS);//用来关闭闲置连接,它会启动一个守护线程进行清理工作。用户可以通过builder#evictIdleConnections开启该组件,并通过builder#setmaxIdleTime设置最大空闲时间。

        httpClient=httpBuilder.build();
    }

    public void destroy() throws Exception{
        if(null != this.httpClient){
            this.httpClient.close();
        }
    }
}


版权声明:本文为qq_41999004原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。