Java Apache HttpAsyncClient内存泄漏

Java Apache HttpAsyncClient内存泄漏,java,memory-leaks,garbage-collection,apache-httpclient-4.x,apache-httpasyncclient,Java,Memory Leaks,Garbage Collection,Apache Httpclient 4.x,Apache Httpasyncclient,我需要在高负载下使用HttpAsyncClient。我创建的HttpAsyncClient如下所示: RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(CONNECT_TIMEOUT) .setSocketTimeout(SOCKET_TIMEOUT) .setConnectionRequestTimeout(CONNECTION_REQUEST_TIME

我需要在高负载下使用HttpAsyncClient。我创建的HttpAsyncClient如下所示:

RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(CONNECT_TIMEOUT)
        .setSocketTimeout(SOCKET_TIMEOUT)
        .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
        .build();
HttpAsyncClient client = HttpAsyncClients.custom()
        .setDefaultRequestConfig(createRequestConfig())
        .build();
HttpPost request = new HttpPost(url);
request.setEntity(new StringEntity(requestBody, "UTF-8"));
client.execute(request, null)
然后我就这样使用它:

RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(CONNECT_TIMEOUT)
        .setSocketTimeout(SOCKET_TIMEOUT)
        .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
        .build();
HttpAsyncClient client = HttpAsyncClients.custom()
        .setDefaultRequestConfig(createRequestConfig())
        .build();
HttpPost request = new HttpPost(url);
request.setEntity(new StringEntity(requestBody, "UTF-8"));
client.execute(request, null)
通常我并不真正关心响应,所以我不初始化
Future
变量,也不执行
Future.get()
。嗯,只是为了澄清一下(我不认为这与问题有关),我有时关心回答,但99%的回答对我来说并不有趣

问题是,当我执行大量请求时(例如每秒300次,这里的“请求”一词是指
client.execute()
invokation),我最终得到
java.lang.OutOfMemoryError:超出了GC开销限制
。我试着用VisualVM来找出发生了什么。我看到
java.lang.Object[]
char[]
java.lang.String
byte[]
short
char[]
实例数正在增加(我试图强制GC并限制堆大小,以确保它不正常-没有帮助)。增加使用的堆空间也是如此

是什么导致了这个问题?也许我应该以不同的方式使用
HttpAsyncClient
?我是否需要使用自定义的
RequestProducer
ResponseProducer
或使用
CountDownLatch

UPD
问题是因为PowerMock库

HttpAsyncClient不会以任何方式或方式限制请求执行速率,以避免阻塞#execute方法。一个人可以向客户机提交无限数量的请求,客户机会尽职尽责地将它们全部放入执行队列。这些请求实际执行和从队列中删除的速度是完全不同的,取决于许多因素。在您的特定情况下,您正试图通过每个路由只有2个并发连接来处理所有这些请求,这不一定是最佳做法


PS://老人的抱怨/人们不应该因为某种原因而认为异步客户端会更快。除非以特定的方式用于特定的用例,否则它们不会被使用。除非非常小心,否则很容易在异步客户机上使用更多内存

原因是我使用PowerMock运行测试。如果没有PowerMock,一切正常。

您有多少个
HttpAsyncClient
实例?我的意思是,您是否为每个请求创建
client
?否,我只有一个
客户端
请查看此链接,您将在本主题中找到解决方案。经典和异步HCs中的连接管理完全不同。4775618中所说的一切与HttpAsyncClient无关,“不会以任何方式或方式限制请求执行速率以避免阻塞#execute方法”-请您再解释一下好吗?我也在考虑客户机内部的这些请求队列。但这里有一件事-我设置了
connectionRequestTimeout
,所以我想我可以确定,如果队列中的请求在5秒内没有获得自己的连接,它将被
TimeoutException
取消。但不知何故,GC似乎无法清理客户端内部的某些东西;第二,可能是管道支持。Ofc我可以在同步客户端上创建某种外观,但这要困难得多-取消支持,一些其他特定功能等,而不是猜测您应该找出哪些没有清理。有什么想法吗?我如何检查它?我查看了
HttpAsyncClient
的源代码,并没有真正找到什么是不能擦除的。据我所知,
InternalHttpAsyncClient
(这是我目前使用的实现)创建一个新的
DefaultClientExchangeHandlerImpl
,并启动它。它尝试从池中获取连接,直到达到超时。在那里,我看不到任何可能导致过时引用或其他问题的问题。不管怎么说,似乎没有任何API可以在外部控制它。在我的问题中是否正确使用了
HttpAsyncClient
?我编写了一个简单的负载测试:。以下是输出的一部分:。出乎意料的是,所有请求都没有执行。如果我在测试的每次迭代中睡眠1000毫秒,那么它工作得非常好。
HttpAsyncClient
管理请求的方式很奇怪。考虑到在
connectionRequest
超时之后,旧请求正在从执行队列中删除,我无法理解队列大小是否有不断增长的可能。顺便说一句,您所说的执行队列是指许多默认ClientExchangeHandlerImpl的实例?