HttpClient 5.2.1版本HTTP/2通信下内存占用与GC性能问题
HttpClient 5.2.1版本HTTP/2通信内存泄漏问题排查求助
我们将用于HTTP/2通信的HttpClient库从5.1版本升级至5.2.1版本后,遇到严重内存异常:连接ALB(应用负载均衡器)暴露的任意端点时,应用内存占用过高且无法高效释放,导致垃圾回收(GC)耗时显著增加。
问题复现情况
- 已提供可运行的示例应用,仅发送100次请求即可观察到内存占用快速上升
- 相同代码切换为HTTP/1.1协议时运行完全正常
- 示例应用内存配置:
-Xms64m -Xmx512m
内存占用对比
HTTP/1.1下内存占用

HTTP/2下内存占用

示例代码
package org.example; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import org.apache.hc.client5.http.async.methods.SimpleHttpResponse; import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.client5.http.config.TlsConfig; import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.protocol.HttpClientContext; import org.apache.hc.core5.concurrent.FutureCallback; import org.apache.hc.core5.http.nio.support.BasicRequestProducer; import org.apache.hc.core5.http2.HttpVersionPolicy; import org.apache.hc.core5.reactor.IOReactorConfig; import org.apache.hc.core5.util.Timeout; public class App { public static void main( String[] args ) throws InterruptedException, IOException { CloseableHttpAsyncClient client = provideHttpAsyncClient(); client.start(); ExecutorService executors = Executors.newFixedThreadPool(8); final CountDownLatch countDownLatch = new CountDownLatch(100); for(int i=0; i< 100; i++) { executors.submit(() -> { try { Thread.sleep(500); client.execute(new BasicRequestProducer("GET", new URI("https://www.figma.com/")), SimpleResponseConsumer.create(),null, HttpClientContext.create(), new FutureCallback<>() { @Override public void completed(SimpleHttpResponse result) { System.out.println(result.getCode() + " " + result.getVersion()); countDownLatch.countDown(); System.out.println("Current heap size " + Runtime.getRuntime().totalMemory()/1000000 + "MB"); } @Override public void failed(Exception ex) { System.out.println("Something went wrong... " + ex); countDownLatch.countDown(); } @Override public void cancelled() { System.out.println("cancelled"); countDownLatch.countDown(); } } ); } catch (InterruptedException | URISyntaxException e) { throw new RuntimeException(e); } }); } countDownLatch.await(); client.close(); System.out.println("Client closed"); } public static CloseableHttpAsyncClient provideHttpAsyncClient() { RequestConfig requestConfig = getRequestConfig(); PoolingAsyncClientConnectionManagerBuilder connectionManagerBuilder = PoolingAsyncClientConnectionManagerBuilder.create() .setMaxConnPerRoute(100) .setMaxConnTotal(30) .setDefaultTlsConfig(prepareTLSConfig()); PoolingAsyncClientConnectionManager connManager = connectionManagerBuilder.build(); IOReactorConfig ioReactorConfig = IOReactorConfig.custom() .setSoTimeout(60, TimeUnit.SECONDS) .build(); return HttpAsyncClients.custom() .setDefaultRequestConfig(requestConfig) .setIOReactorConfig(ioReactorConfig) .setConnectionManager(connManager) .build(); } static private TlsConfig prepareTLSConfig() { HttpVersionPolicy httpVersionPolicy = HttpVersionPolicy.FORCE_HTTP_1; return new TlsConfig.Builder().setVersionPolicy(httpVersionPolicy).build(); } static RequestConfig getRequestConfig() { RequestConfig.Builder builder = RequestConfig.custom() .setResponseTimeout( Timeout.ofSeconds( 15)) // Timeout until a new connection is fully // established .setConnectionRequestTimeout(Timeout.ofSeconds(60)) .setResponseTimeout(Timeout.ofSeconds(60)); return builder.build(); } }
我们尝试使用OkHTTP库执行相同操作,运行情况完全正常。恳请协助定位问题原因并提供可行的解决方案。
内容的提问来源于stack exchange,提问作者Sandeep Gaur
相关产品推荐
相关产品推荐

