2

我需要在高负载下使用 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 个,这里的“请求”一词是指client.execute()调用)我终于得到了java.lang.OutOfMemoryError: GC overhead limit exceeded. 我尝试使用 VisualVM 来了解发生了什么。我看到 , , , , ,java.lang.Object[]实例char[]java.lang.String正在byte[]增长(我试图强制 GC 并限制堆大小以确保它不正常 - 没有帮助)。使用的堆空间也在增加。shortchar[]

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

UPD 问题是因为PowerMock库

4

2 回答 2

3

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

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

于 2016-01-15T14:47:15.130 回答
0

原因是我使用 PowerMock 来运行我的测试。没有 PowerMock 一切正常。

于 2016-01-21T11:04:38.680 回答