我需要在高负载下使用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)


通常,我不太在乎响应,所以我不初始化Future<HttpResponse>变量,也不做Future.get()。好吧,只是为了澄清(我认为这与问题无关),我有时会在乎回复,但是99%的回复对我来说并不有趣。

问题是当我执行大量请求时(例如每秒300个,这里用“ request”一词指的是client.execute()调用),我终于得到了java.lang.OutOfMemoryError: GC overhead limit exceeded。我试图使用VisualVM找出正在发生的事情。我发现java.lang.Object[]char[]java.lang.Stringbyte[]shortchar[]实例数量正在增长(我试图强制GC并限制堆大小以确保它不正常-没有帮助)。因此,增加了使用的堆空间。

是什么导致此问题?也许我应该以其他方式使用HttpAsyncClient?我需要使用自定义RequestProducerResponseProducer还是使用CountDownLatch

UPD
问题是由于PowerMock库

最佳答案

HttpAsyncClient不会以任何方式或方式来限制请求的执行速度,以避免阻塞#execute方法。一个人可以向客户端提交无数个请求,客户端将尽职尽责地将所有请求都放入执行队列中。实际执行这些请求并将其从队列中删除的速度是完全不同的情况,并且可能取决于许多因素。在您的特定情况下,您尝试处理每个路由仅具有2个并发连接的所有这些请求,这不一定是最佳选择。

PS:/老人的抱怨/人们不应该因为某些原因而认为异步客户端会更快。除非将其用于特定用例并以特定方式使用,否则它们将不会被使用。可以肯定的是,除非非常小心,否则异步客户端可能会轻易使用更多的内存。

10-02 00:33