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

时间:2024-10-14 18:27:54

[背景]
应用中线程数量 一直在增加,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 : ,
                        maxIdleTime, maxIdleTimeUnit);
                (new Closeable() {

                    @Override
                    public void close() throws IOException {
                        ();
                        try {
                            (1L, );
                        } catch (final InterruptedException interrupted) {
                            ().interrupt();
                        }
                    }

                });
                ();//这里会创建evaictor线程
            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

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

public class HttpClientFactory {
    private CloseableHttpClient httpClient;

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

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

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

        httpClient=();
    }

    public void destroy() throws Exception{
        if(null != ){
            ();
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34