1. Введение
В этом уроке мы сравним две реализации веб-клиента Spring —RestTemplateи новая альтернатива Reactive в Spring 5WebClient.
2. Блокирующие и неблокирующие клиенты
В веб-приложениях выполнение HTTP-вызовов к другим службам является очень распространенным требованием. Поэтому нам нужен веб-клиент.
2.1. RestTemplateблокирующий клиент
Долгое время Весна давалаRestTemplateАбстракция как веб-клиент. внизу,RestTemplate использует API сервлетов Java на основе модели «поток на запрос».
Это означает, что поток будет заблокирован до тех пор, пока веб-клиент не получит ответ. Проблема с блокирующим кодом заключается в том, что каждый поток потребляет определенное количество памяти и циклов процессора.
Предположим, что есть много входящих запросов, ожидающих получения результатов каким-то медленным сервисом.
Рано или поздно запросы, ожидающие результатов, накапливаются. **В результате программа создаст множество потоков, которые либо исчерпают пул потоков, либо займут всю доступную память. ** Мы также наблюдаем снижение производительности из-за частого переключения контекста ЦП (потока).
2.2. WebClientнеблокирующий клиент
с другой стороны,WebClient использует асинхронное неблокирующее решение, предоставляемое Spring Reactive Framework.
когдаRestTemplateСоздавать новый для каждого события (HTTP-запроса)нитьчас,WebClientДля каждого события будет создано что-то вроде «задачи». За кулисами Reactive framework поставит эти «задачи» в очередь и выполнит их только тогда, когда будет доступен соответствующий ответ.
Фреймворк Reactive использует архитектуру, управляемую событиями. он обеспечивает черезReactive Streams APIСпособы составления асинхронной логики. Следовательно, Reactive может обрабатывать больше логики, используя меньше потоков и системных ресурсов, чем синхронизированные/блокирующие методы.
WebClientдаSpring WebFluxчасть библиотеки. следовательно,Мы также можем написать код на стороне клиента, используя гибкий функциональный API, и составить типы ответов (Mono и Flux) в виде объявлений.
3. Сравнение случаев
Чтобы продемонстрировать разницу между двумя подходами, нам нужно запустить тесты производительности с множеством одновременных клиентских запросов. После определенного количества одновременных запросов мы увидим значительное падение производительности метода блокировки.
С другой стороны, реактивный/неблокирующий подход может обеспечить постоянную производительность независимо от количества запросов.
Для целей этой статьи давайте реализуем две конечные точки REST, одну с помощью RestTemplate, а другую с помощью WebClient. ** Их задача — вызвать другой медленный веб-сервис REST, который возвращает список твитов.
Во-первых, нам нужно представитьНачальные зависимости Spring Boot WebFlux:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Далее, вот наша конечная точка медленного сервиса REST:
@GetMapping("/slow-service-tweets")
private List<Tweet> getAllTweets() {
Thread.sleep(2000L); // delay
return Arrays.asList(
new Tweet("RestTemplate rules", "@user1"),
new Tweet("WebClient is better", "@user2"),
new Tweet("OK, both are useful", "@user1"));
}
3.1 ИспользованиеRestTemplateпозвони в медленную службу
Теперь давайте реализуем другую конечную точку REST, которая будет вызывать нашу медленную службу через веб-клиент.
Во-первых, давайте использоватьRestTemplate:
@GetMapping("/tweets-blocking")
public List<Tweet> getTweetsBlocking() {
log.info("Starting BLOCKING Controller!");
final String uri = getSlowServiceUri();
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<List<Tweet>> response = restTemplate.exchange(
uri, HttpMethod.GET, null,
new ParameterizedTypeReference<List<Tweet>>(){});
List<Tweet> result = response.getBody();
result.forEach(tweet -> log.info(tweet.toString()));
log.info("Exiting BLOCKING Controller!");
return result;
}
Когда мы называем эту конечную точку, посколькуRestTemplateСинхронный характер кода заблокирует ожидание ответа от медленной службы. Остальной код в этом методе будет выполняться только после получения ответа. Через лог мы видим:
Starting BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)
Exiting BLOCKING Controller!
3.2 ИспользованиеWebClientпозвони в медленную службу
Во-вторых, воспользуемсяWebClientЧтобы вызвать медленную службу:
@GetMapping(value = "/tweets-non-blocking",
produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Tweet> getTweetsNonBlocking() {
log.info("Starting NON-BLOCKING Controller!");
Flux<Tweet> tweetFlux = WebClient.create()
.get()
.uri(getSlowServiceUri())
.retrieve()
.bodyToFlux(Tweet.class);
tweetFlux.subscribe(tweet -> log.info(tweet.toString()));
log.info("Exiting NON-BLOCKING Controller!");
return tweetFlux;
}
В этом примереWebClientвернутьFluxВыполнение метода завершается после производителя. Как только результаты будут доступны, издатель начнет рассылать твиты своим подписчикам. Обратите внимание, что вызов/tweets-non-blockingКлиенты этой конечной точки (в данном случае веб-браузеры) также подпишутся на возвращаемыйFluxобъект.
Давайте посмотрим на журнал на этот раз:
Starting NON-BLOCKING Controller!
Exiting NON-BLOCKING Controller!
Tweet(text=RestTemplate rules, username=@user1)
Tweet(text=WebClient is better, username=@user2)
Tweet(text=OK, both are useful, username=@user1)
Обратите внимание, что метод этой конечной точки завершается до получения ответа.
4. Вывод
В этой статье мы рассмотрели два разных способа использования веб-клиента в Spring.
RestTemplateИспользует Java Servlet API и поэтому является синхронным и блокирующим. Напротив,WebClientявляется асинхронным и не блокирует исполняемый поток, ожидая возврата ответа.Уведомления генерируются только тогда, когда программа готова.
RestTemplateвсе еще будет использоваться. Но в некоторых случаях неблокирующие методы используют гораздо меньше системных ресурсов, чем блокирующие. Поэтому в этих случаяхWebClientВсе же лучший выбор.
Все фрагменты кода, упомянутые в этой статье, можно найти вGitHubнайти на.
оригинал:Woohoo. Поместите Arlington Terrier.com/spring-weblayer…
автор:Drazen Nikolic
Переводчик: Ваньсян
Отправка преимуществ ~ Недавно переведенные ранее статьи были организованы в формате PDF. Ответить на фоне публичного аккаунта: 002, чтобы получить его~ Мы продолжим обновлять содержимое PDF-файла в будущем, так что следите за обновлениями!