Вопрос по jersey, jax-rs, java, rest – Предотвращение клиента Джерси от возникновения ошибки вне памяти при публикации больших файлов

12

При размещении больших файлов в качестве InputStream с использованиемДжерси клиент, кажется, что все содержимое файла буферизируется в памяти перед отправкой на сервер. Это вызывает проблему с большими файлами, поскольку JVM не хватает места в куче. Как я могу предотвратить такое поведение в клиенте Джерси? Методы ресурсов JAX-RS на стороне сервера, по-видимому, не имеют этой проблемы при отправке данных.

Например:

WebResource dataUploadResource = buildDataUploadResource();
dataUploadResource.type(getMimeType()).put(getLargeInputStream());

Ваш Ответ

1   ответ
13

вам необходимо настроить клиент Jersey для использования chunked encoding1 по запросу. Это устраняет необходимость устанавливать заголовок Content-Length и будет транслироваться из предоставленного InputStream без буферизации всего содержимого в памяти.

По умолчанию Джерси использует класс HttpURLConection JDK для обработки HTTP-запросов и ответов. К сожалению, в этом есть некоторые ошибки, связанные с частичной передачей кодирования. К счастью, у Джерси есть точки расширения, позволяющие использовать различные реализации HTTP-клиентов. Одна такая реализация основана на Apache Http Client2.

Существуют две реализации клиентского обработчика apache htpp, одна поддерживает версию 3.x с окончанием срока службы, другая использует более новую версию 4.x. Для нашего проекта мы использовали реализацию, основанную на более старой (3.1) версии. Библиотека доступна в Maven Central под «вкладками». подгруппа.

<dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-apache-client</artifactId>
    <version>1.14</version>
</dependency>

Затем вы должны инициализировать свой клиент Джерси, чтобы использовать новую реализацию:

Client jerseyClient = ApacheHttpClient.create(getClientConfig());

Чтобы включить кодирование по частям, вам необходимо установить размер кодирования по частям в конфигурации клиента, поскольку он не включен по умолчанию:

private ClientConfig getClientConfig() {
   ClientConfig config = new DefaultClientConfig();

   config.getProperties().put(
            DefaultApacheHttpClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0);
   return config;
}

Пока это свойство неnullбудет использоваться чанкованная кодировка. Фактически, версия 1.14 игнорирует размер кодировки, поскольку указание размера не поддерживается базовой библиотекой apache commons-httpclient.

К сожалению, это, похоже, не работает надежно - вот почему мы по частям закомментировали кодировку по умолчанию в коде Джерси. Кажется, в HttpURLConnection есть неприятная ошибка, из-за которой некоторые запросы странным образом и полу-случайным образом терпят неудачу (подмножество наших тестов завершается неудачей, если мы перезапускаем только провальные тесты, то меньшее подмножество их не выполняется, если мы повторно запускаем только это подмножество, даже меньшее подмножество терпит неудачу и в конце концов все проходит). Поэтому я рекомендую использовать более надежный клиентский коннектор для любой серьезной работы.
Спасибо за ваш отзыв. Я обновил ответ, чтобы показать, как настроить клиент для использования кускового кодирования с использованием клиентского соединителя Apache Http. Eric

Похожие вопросы