Рубрики
Без рубрики

Запросите Буферизацию Тела С помощью RestTemplate Spring

Предыстория Я уже некоторое время использую Java Spring framework для своей работы. Я звезда… С тегами технология, java, весна, весенняя загрузка.

Я уже некоторое время использую Java Spring framework для своей работы. Я начал изучать платформу Spring во время создания приложения REST API, которое должно было подключаться к другим удаленным службам через их собственный интерфейс REST API. В то время как Spring RestTemplate в настоящее время находится только в режиме обслуживания и, как ожидается, в будущем полностью устареет, это было первое, что я нашел для выполнения HTTP-запросов в Spring framework. Так что я просто начал использовать его из соображений практичности.

Теперь мы часто хотим регистрировать HTTP-запросы, которые делают наши серверы. Один из способов – поместить операторы журнала везде, где нам нужно было совершать HTTP-вызовы. Одной из альтернатив с помощью Spring RestTemplate является настройка перехватчика ведения журнала . Таким образом, мы можем настроить глобальные (или несколько) шаблонов Rest, в которых настроена возможность ведения журнала.

public class LoggingInterceptor implements ClientHttpRequestInterceptor {

        static Logger log = LoggerFactory.getLogger(LoggingInterceptor.class);

        @Override
        public ClientHttpResponse intercept(HttpRequest req, byte[] reqBody, ClientHttpRequestExecution ex)
          throws IOException {
            log.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8));
            ClientHttpResponse response = ex.execute(req, reqBody);
            InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8);
            String body = new BufferedReader(isr)
              .lines()
              .collect(Collectors.joining("\n"));
            log.debug("Response body: {}", body);
            return response;
        }
    }

Взяв из сообщения Baeldung выше, мы можем видеть, что подпись для метода перехват содержит тело запроса параметр типа байт [] . Это означает, что для регистрации тела исходящего запроса Spring должен сериализовать все, что мы отправляем, в структуру массива байтов в памяти. В зависимости от отправляемого вами тела запроса это может вызвать проблемы с памятью и, возможно, даже ошибки нехватки памяти. Кроме того, это, вероятно, влияет на производительность вашего приложения, даже если немного. Так что это то, что может потребовать некоторых соображений.

Теперь в моем текущем проекте я должен ретранслировать загруженные файлы, созданные клиентами, в другую службу через ее вызов API. Эти файлы потенциально могут иметь размер в гигабайтах. Все еще используя RestTemplate, я сразу понимаю, что у приложения закончится память, если я войду в систему с помощью описанного выше перехватчика. Поэтому я решил создать два вида RestTemplate: один, который может автоматически регистрировать запросы, и другой, который этого не делает. Кроме того, я использовал HttpComponentsClientHttpRequestFactory.setbufferrequestbody(false) , чтобы гарантировать, что приложение не будет буферизировать загруженный файл, который необходимо ретранслировать.

Но когда я функционально тестировал приложение, я продолжал работать с ошибками нехватки памяти при загрузке файла объемом 1,5 ГБ, и что бы я ни делал, я не мог это исправить. После дальнейшего расследования выясняется, что я не знал, что Привод пружинной загрузки доступен в пути к классам. Одна из вещей, которую предоставляет пакет Actuator, – это набор метрик исходящих HTTP-клиентов, созданных resttemplates, который автоматически предоставляется, если мы создаем нашу RestTemplate с помощью автоматически настроенного RestTemplateBuilder , предоставляемого SpringBoot. То есть, если бы мы создали нашу RestTemplate следующим образом:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder.build();
}

затем автоматически настраивается возможность сбора показателей. И, конечно же, сбор метрик выполняется путем добавления перехватчика, если быть точным, используется Настройщик шаблона Rest метрик . Этот перехватчик добавляется в Конструктор шаблонов Rest Я использовал выше для создания RestTemplate , и поэтому все мои запросы, сделанные с помощью RestTemplate то, что не было настроено для ведения журнала, на самом деле буферизовало тело запроса! Неудивительно, что я продолжал попадать в ошибки ООМ…

Ну, исправление на самом деле довольно простое, я только что создал RestTemplate без настроенного Rest TemplateBuilder , и все в порядке! Ну… в конце концов я решил перенести приложение на использование WebClient вместо этого. Мало того, что это предлагаемый API для использования сейчас, таким образом, я создаю приложение для будущего доказательства, я все равно смогу регистрировать запросы без необходимости принудительного буферизации тела запроса. Хотя, если я захочу зарегистрировать тело запроса программно, мне все равно потребуется буферизировать тело запроса, но это отдельная проблема на будущее.

Оригинал: “https://dev.to/btruhand/request-body-buffering-with-spring-s-resttemplate-1958”