Утечка памяти в 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: /ворчит старик/ люди не должны предполагать, что асинхронные клиенты по какой-то причине будут работать быстрее. Они не будут использоваться, если не используются для конкретных случаев использования и определенным образом. Несомненно, что можно легко использовать больше памяти с асинхронными клиентами, если не соблюдать осторожность.