HttpClient 引发的线程太多,导致FullGc

CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(connectionManager)
        .setMaxConnTotal(400)
        .setMaxConnPerRoute(150)
        .evictExpiredConnections()
        .build();

evictExpiredConnections  这个配置作用:

设置一个定时线程,定时清理闲置连接,可以将这个定时时间设置为 keep alive timeout 时间的一半以保证超时前回收

 

每个httpClient 对象都会有自己独立的定时线程

 

 

这样如果应用中httpClient对象很多,就会导致上图中线程太多

 

源码中,如果设置了evictExpiredConnections  会有下面一段逻辑

        List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;
        if (!this.connManagerShared) {
            if (closeablesCopy == null) {
                closeablesCopy = new ArrayList<Closeable>(1);
            }
            final HttpClientConnectionManager cm = connManagerCopy;

            if (evictExpiredConnections || evictIdleConnections) {
                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();
            }
            closeablesCopy.add(new Closeable() {

                @Override
                public void close() throws IOException {
                    cm.shutdown();
                }

            });
        }
IdleConnectionEvictor  对象是
public final class IdleConnectionEvictor {

    private final HttpClientConnectionManager connectionManager;
    private final ThreadFactory threadFactory;
    private final Thread thread;
    private final long sleepTimeMs;
    private final long maxIdleTimeMs;

    private volatile Exception exception;

    public IdleConnectionEvictor(
            final HttpClientConnectionManager connectionManager,
            final ThreadFactory threadFactory,
            final long sleepTime, final TimeUnit sleepTimeUnit,
            final long maxIdleTime, final TimeUnit maxIdleTimeUnit) {
        this.connectionManager = Args.notNull(connectionManager, "Connection manager");
        this.threadFactory = threadFactory != null ? threadFactory : new DefaultThreadFactory();
        this.sleepTimeMs = sleepTimeUnit != null ? sleepTimeUnit.toMillis(sleepTime) : sleepTime;
        this.maxIdleTimeMs = maxIdleTimeUnit != null ? maxIdleTimeUnit.toMillis(maxIdleTime) : maxIdleTime;
        this.thread = this.threadFactory.newThread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (!Thread.currentThread().isInterrupted()) {
                        Thread.sleep(sleepTimeMs);
                        connectionManager.closeExpiredConnections();
                        if (maxIdleTimeMs > 0) {
                            connectionManager.closeIdleConnections(maxIdleTimeMs, TimeUnit.MILLISECONDS);
                        }
                    }
                } catch (final Exception ex) {
                    exception = ex;
                }

            }
        });
    }

会出现一个线程,这个线程里面就是去关闭超时不用的闲置链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpClient是一种HTTP客户端库,可以用于发送HTTP请求和接收HTTP响应。 如果你需要在多线程环境下使用HttpClient,你需要保证多个线程共享同一个HttpClient实例。这是因为HttpClient线程安全的,可以重复使用,可以复用连接,从而提高性能。 以下是使用HttpClient进行多线程请求的示例代码: ```java CloseableHttpClient httpClient = HttpClients.createDefault(); ExecutorService executorService = Executors.newFixedThreadPool(5); List<Callable<String>> tasks = new ArrayList<>(); tasks.add(() -> { HttpGet httpGet = new HttpGet("http://www.baidu.com"); CloseableHttpResponse response = httpClient.execute(httpGet); String result = EntityUtils.toString(response.getEntity()); return result; }); tasks.add(() -> { HttpGet httpGet = new HttpGet("http://www.google.com"); CloseableHttpResponse response = httpClient.execute(httpGet); String result = EntityUtils.toString(response.getEntity()); return result; }); List<Future<String>> futures = executorService.invokeAll(tasks); for (Future<String> future : futures) { System.out.println(future.get()); } executorService.shutdown(); httpClient.close(); ``` 在这个示例中,我们创建了一个可以复用的HttpClient实例,并使用ExecutorService来启动多个任务。每个任务都发送一个HTTP请求,并返回响应内容。我们可以使用Future来获取每个任务的结果,并在最后打印出来。 要注意的是,当使用多线程时,HttpClient可能会同时发起多个请求,这可能会导致服务器拒绝服务或响应缓慢。因此,我们建议使用连接池来限制并发请求数量。如果需要使用连接池,可以使用HttpClients.createDefault方法创建一个带连接池的HttpClient实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值