Утечка памяти в Apache HttpAsyncClient
Мне нужно использовать 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[]
, short
, char[]
количество экземпляров растет (я пытался заставить GC и ограничить размер кучи, чтобы убедиться, что это не нормально - не помогло). И так растет используемое пространство кучи.
Что вызывает эту проблему? Может быть, я должен использовать HttpAsyncClient
каким-то другим способом? Нужно ли использовать кастом RequestProducer
, ResponseProducer
или использовать CountDownLatch
?
UPD Проблема была из-за библиотеки PowerMock
2 ответа
Причина была в том, что я использовал PowerMock для запуска своих тестов. Без PowerMock все работает нормально.
HttpAsyncClient не ограничивает скорость выполнения запросов каким-либо образом или способом, чтобы избежать блокировки метода #execute. Можно отправить клиенту неограниченное количество запросов, и клиент покорно вставит их все в очередь выполнения. То, насколько быстро эти запросы могут быть действительно выполнены и удалены из очереди, - это совсем другая история и может зависеть от многих факторов. В вашем конкретном случае вы пытаетесь обработать все эти запросы всего с двумя одновременными соединениями на маршрут, что не всегда может быть оптимальным решением.
PS: /ворчит старик/ люди не должны предполагать, что асинхронные клиенты по какой-то причине будут работать быстрее. Они не будут использоваться, если не используются для конкретных случаев использования и определенным образом. Несомненно, что можно легко использовать больше памяти с асинхронными клиентами, если не соблюдать осторожность.