webflux spring что это

WebSockets и Spring WebFlux

Все мы знаем вебсокеты, любим или не очень и можем написать их со Spring MVC.

А что на счет реактивного приложения?

В этой статье будет рассмотрено как создать вебсокеты с помощью Spring WebFlux.

Для создания проекта использовалась страница start.spring.io с зависимостью Reactive Web.

Как сконфигурировать вебсокет

Начнем с конфигурации, чтобы наглядно продемонтрировать почему нам нужен тот или иной компонет.

Первое что нужно сделать это написать конфигурацию для реактивного вебсокета.

Для этого нужно два бина: HandlerMapping и HandlerAdapter.

HandlerAdapter создается довольно таки легко:

Зачем нужен этот бин?

Адаптер внутри себя инициализирует вебсокет сервис и использует (еще не написанную нами) имплементацию WebSocketHandler. Другими словами, этот бин включает вебсокет в Spring WebFlux.

Следующий бин это HandlerMapping. С помощью него мы можем настроить url и отвечающий за него WebSocketHandler, а так же порядок инициализации бина. Спринг будет знать как настоить нужный url и как его обрабатывать благодяря этой конфигурации. Наш url будет выглядить так http://localhost:8080/push, так как ниже мы настраиваем путь как /push.

Конечно можно создавать сколько угодно url и WebSocketHandler.

Теперь можно создать имплементацию WebSocketHandler. С этим классом мы можем обрабатывать объект WebSocketSession, другими словами читать и отправлять сообщения.

На данный момент мы оставим Mono.empty(), но не волнуйтесь, ниже будет полноценная имплементация.

Полный код конфигурации.

Как прочитать сообщение?

Логика чтения может быть реализована в имплементации интерфейса WebSocketHandler.

Нам нужно использовать объект WebSocketSession и просто вызывать метод receive(), чтобы получить стрим и обработать его.

Как отправить сообщение?

Перед тем как продолжить изменять WebSocketHandler нужно создать какой-то простенький дата класс, который мы будем слать клиенту.

Так же нужно создать сервис, который сможет возвращать ивенты в виде реактивного стрима (как требует WebSocketSession).

Главное: нужно добавлсять новые ивенты в стрим.

Так что теперь может создать наш интерфейс:

Имплементация будет использовать EmitterProcessor, который подходит под все наши требования. Этот процессор может потреблять наши ивенты и раздавать подписчикам.

Так же можно использовать метод replay(int), который кэширует указанное количество элементов и возвращает новым подписчикам.

Отправка сообщений будет выглядить вот так:

Как видно из кода выше, перед тем как отправить объект клиенту, его нужно сконвертировать в json. Spring WebFlux не предоставляет механизм для десериализации объекта в json для вебсокетов.

В примере используется Jackson, а именно ObjectMapper#writeValueAsString, так что на выходе мы имеем json строку.

Теперь можно объединить чтение и отправку в DefaultWebSocketHandler.

Event generator

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

Не забываем включить Scheduler в приложении.

Клиент

Для клиента будет использоваться Angular.

Здесь мы используем rxjs websockets.

Чтобы увидеть наши сообщения надо обновить app.component.html.

Теперь можно запустить приложение и открыть в браузере localhost:4200.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Рекомендации как обезопасить вебсокеты

Выводы

В статье показана базовые кофигурация, чтение и отправка сообщений используя реактивные вебсокеты, которое было рассмотрено на примере демопроекта. Так же можно увидеть, что реализация упирается в знание Project Reactor.

Источник

Spring WebFlux: Реактивное программирование веб-сервисов

Особенности: преимущества и недостатки

Модуль WebFlux появился в 5й версии фреймворка Spring. Этот микрофреймворк является альтернативой Spring MVC и отражает собой реактивный подход для написания веб-сервисов. В основе WebFlux лежит библиотека Project Reactor, позволяющая легко запрограммировать неблокирующие (асинхронные) потоки (streams), работающие с вводом/выводом данных.

Следует учесть, что WebFlux для работы требуется встроенный в Spring сервер Netty. Встроенные Tomcat и Jetty не подходят. Следующая диаграмма иллюстрирует особенности окружения, в котором работает WebFlux [1].

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

График внизу демонстрирует преимущество в производительности реактивных веб-сервисов [2] по сравнению с обычными, блокирующими. При загруженности сервера в 300 и более пользователей Netty начинает превосходить Tomcat по количеству одновременно обрабатываемых запросов. При предельной загруженности сервера в реактивном режиме может одновременно обслуживаться в 2 раза больше пользователей. По другим источникам преимущество не так внушительно, но заметно. Наибольший эффект реактивное программирование дает при вертикальном масштабировании.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Важная особенность реактивности еще в том, что она дает слабую связность. Например, если между клиентом и сервисом происходит разрыв соединения, оно воссоздается при восстановлении Интернет. Ограничения во времени не требуется, так-как соединение происходит для отдельного потока, не влияющего на другие. Но при этом реактивный подход должен быть реализован на обеих сторонах.

Программировать приложение с множеством неблокирующих потоков достаточно непривычная задача. Требуется особый подход и стиль программирования, основанный на лямбда-выражениях с использованием реактивных библиотек. Библиотека Project Reactor, входящая в WebFlux, отличается от реактивной библиотеки RxJava (реализованной, например, в Android) тем, что больше подходит для бэкэнда. Например, устранены некоторые проблемы, которые могут вызвать нехватку памяти.

К неудобствам реактивного программирования следует отнести более ограниченный инструментарий для работы с реляционными БД. Например, JPA-библиотеки Hibernate и EclipseLink не поддерживают реактивность. Невозможно в Java описывать сложные связи между объектами, как это делается обычно тегами @Entity, @OneToMany, @ManyToMany, @JoinTable и т.д.. Не получится программно описать ограничение целостности таблиц. Хотя это придает большую гибкость используемой БД. Для привязки классов к таблицам достаточно тегов @Table и @Column. Языки JPQL (HQL) не годятся для реактивных запросов к БД. Но при этом доступен нативный SQL. Вместо JDBC потребуется R2DBC. Об этом чуть позже.

Простейший пример реактивного REST-сервиса и REST-клиента

Для разработки реактивного сервиса достаточно в pom.xml добавить модуль spring-boot-starter-webflux, вместо обычного spring-boot-starter-web в Spring MVC.

Кодирование REST сервисов и их клиентов в Spring WebFlux может полностью совпадать со Spring MVC. Отличие только в определении возвратов. На выходе методов в WebFlux мы добавляем Mono (или в особых случаях Flux, когда требуется последовательно в одном потоке передать несколько объектов). Например, метод sendSms контроллера SmsController

обращается к методу sendSms сервиса SmsService:

Цепочка методов smsClient.post().bodyValue() может заканчиваться методом retrieve().bodyToMono(), если не требуется дальнейшая обработка и преобразование объектов передаваемых клиентом. Иначе, как в примере, требуется exchange().flatMap( ).

Реактивный клиент в Spring определяется только через WebClient. Шаблон RestTemplate (из Spring MVC) не подходит. Подробнее о реактивных REST-сервисах здесь [3].

Работа с реактивными реляционными БД: Особенности

Для подключения реактивных реляционных библиотек через Maven в pom.xml потребуется добавить две зависимости. Пример для PostgreSQL.

org.springframework.data
spring-data-r2dbc

io.r2dbc
r2dbc-postgresql

Приятным сюрпризом при переходе с JPA на R2DBC будет уменьшение размера, собираемого джарника приложения, на пару десятков мегабайт. Зависимость spring-boot-starter-data-jpa тянет множество библиотек, требуемых для поддержки JPA.

Вот как выглядит описание реактивного CRUD-репозитария

В примере объекты, возвращаемые запросами к БД, определяются классом Client приблизительно такого вида:

Поля имеют примитивные типы. Мы не описываем вложенные объекты User или PersonData. К этим объектам потребуется обращаться отдельными запросами зная userId или personId. Для ускорения, конечно лучше использовать один объединенный SELECT с JOIN из нативного SQL. Для JPA в подобных случаях (когда объекты не требуются) используют lazy loading.

Источник

Реактивное программирование со Spring, часть 3 WebFlux

1. Введение в Spring WebFlux

WebFlux был представлен как часть Spring Framework 5.0. В отличие от Spring MVC, он не требует Servlet API. Он полностью асинхронный и неблокирующий, реализует спецификацию Reactive Streams через проект Reactor (см. предыдущий пост в блоге ).

WebFlux требует Reactor в качестве основной зависимости, но он также может взаимодействовать с другими реактивными библиотеками через Reactive Streams.

1.1 Модели программирования

Spring WebFlux поддерживает две разные модели программирования: на основе аннотаций и функциональную.

1.1.1 Аннотированные контроллеры

Если вы работали со Spring MVC, модель на основе аннотаций будет выглядеть довольно знакомой, поскольку в ней используются те же аннотации из веб-модуля Spring, что и в Spring MVC. Основное отличие состоит в том, что теперь методы возвращают реактивные типы Mono и Flux. См. Следующий пример RestController с использованием модели на основе аннотаций:

Некоторые пояснения к функциям, использованным в примере:

map функция используется для преобразования элемента, испускаемого Mono, применяя функцию синхронной к нему.

flatMap функция используется для преобразования элемент, испускаемый Mono асинхронно, возвращая значение, излучаемого другим Mono.

1.1.2 Функциональные конечные точки

HandlerFunctions используются для генерации ответа на данный запрос:

RouterFunction используется для маршрутизации запросов к HandlerFunctions:

Продолжая с тем же примером ученика, мы получим что-то вроде следующего, используя функциональный стиль.

Некоторые пояснения к функциям, использованным в примере:

Сравнивая две модели, мы видим, что:

Для использования функционального варианта требуется еще немного кода для таких вещей, как получение входных параметров и синтаксический анализ до ожидаемого типа.

Не полагаясь на аннотации, но написание явного кода предлагает некоторую большую гибкость и может быть лучшим выбором, если нам, например, нужно реализовать более сложную маршрутизацию.

1.2 Поддержка сервера

WebFlux работает в средах выполнения, отличных от сервлетов, таких как Netty и Undertow (неблокирующий режим), а также в средах выполнения сервлетов 3.1+, таких как Tomcat и Jetty.

По умолчанию стартер Spring Boot WebFlux использует Netty, но его легко переключить, изменив зависимости Maven или Gradle.

Например, чтобы переключиться на Tomcat, просто исключите spring-boot-starter-netty из зависимости spring-boot-starter-webflux и добавьте spring-boot-starter-tomcat:

1.3 Конфигурация

Spring Boot обеспечивает автоматическую настройку Spring WebFlux, которая хорошо работает в общих случаях. Если вам нужен полный контроль над конфигурацией WebFlux, можно использовать аннотацию @EnableWebFlux (эта аннотация также потребуется в простом приложении Spring для импорта конфигурации Spring WebFlux).

Если вы хотите сохранить конфигурацию Spring Boot WebFlux и просто добавить дополнительную конфигурацию WebFlux, вы можете добавить свой собственный класс @Configuration типа WebFluxConfigurer (но без @EnableWebFlux).

Подробные сведения и примеры см. в документации по конфигурации WebFlux.

2. Защита ваших конечных точек

Чтобы получить поддержку Spring Security WebFlux, сначала добавьте в свой проект зависимость spring-boot-starter-security. Теперь вы можете включить его, добавив @EnableWebFluxSecurity аннотацию в свой класс Configuration (доступно с Spring Security 5.0).

В следующем упрощенном примере будет добавлена ​​поддержка двух пользователей, один с ролью USER, а другой с ролью ADMIN, принудительно применить базовую аутентификацию HTTP и потребовать роль ADMIN для любого доступа к пути /student/admin:

Также можно защитить метод, а не путь, сначала добавив аннотацию @EnableReactiveMethodSecurity к вашей конфигурации:

А затем добавляем @PreAuthorize аннотацию к защищаемым методам. Например, мы можем захотеть, чтобы наши методы POST, PUT и DELETE были доступны только для роли ADMIN. Затем к этим методам можно применить аннотацию PreAuthorize, например:

Spring Security предлагает дополнительную поддержку, связанную с приложениями WebFlux, например защиту CSRF, интеграцию OAuth2 и реактивную аутентификацию X.509. Для получения дополнительной информации прочтите следующий раздел в документации Spring Security: Реактивные приложения

3. Веб-клиент

Spring WebFlux также включает реактивный, полностью неблокирующий веб-клиент. У него есть функциональный, свободный API, основанный на Reactor.

Давайте рассмотрим (еще раз) упрощенный пример того, как WebClient можно использовать для запроса нашего StudentController:

4. Тестирование

Для тестирования вашего реактивного веб-приложения WebFlux предлагает WebTestClient, который поставляется с API, аналогичным WebClient.

Давайте посмотрим, как мы можем протестировать наш StudentController с помощью WebTestClient:

5. WEBSOCKETS и RSOCKET

5.1 Веб-сокеты

В Spring 5 WebSockets также получает дополнительные реактивные возможности. Чтобы создать сервер WebSocket, вы можете создать реализацию WebSocketHandler интерфейса, которая содержит следующий метод:

WebSocketSession имеет методы, определенные для обработки входящих и исходящих потоков:

Spring WebFlux также предоставляет WebSocketClient реализации для Reactor Netty, Tomcat, Jetty, Undertow и стандартной Java.

Для получения дополнительной информации прочтите следующую главу в документации Spring’s Web on Reactive Stack: WebSockets

5.2 RSOCKET

А для получения дополнительной информации о поддержке Spring Framework протокола RSocket

6. Подводя итог…

Источник

Spring MVC vs Spring WebFlux. Что лучше? Объясняем на пингвинах

Существует множество способов реализации REST-API. Большой популярностью пользуется Spring MVC на основе блокирующих вызовов, но все чаще попадаются проекты, использующие WebFlux на неблокирующих вызовах. Меня зовут Альберт Фатхудинов. Я Java-разработчик Технократии. В этой статье буду разбираться, какой из этих двух фреймворков работает лучше.

Технологии, которые использовали

Дисклеймер, в котором перечислим технологии, которые применялись в эксперименте:

Apache JMeter — для нагрузочного тестирования

VisualVm — для профилирования

MongoDb — NoSql База данных

PostgreSql — реляционная база данных

Netty — серверная среда неблокирующего ввода/вывода для разработки сетевых приложений

Apache Tomcat — контейнер сервлетов

Spring MVC — Фреймворк, обеспечивает архитектуру паттерна MVC при помощи слабо связанных готовых компонентов

Spring WebFlux — фреймворк, реализующий парадигму реактивного программирования, добавлен в Spring 5+

На этом дисклеймер закончился. Поехали!

Архитектура тестового приложения

Представим абстрактного пингвина, которого зовут Шкипер. Он хочет узнать о своих последних штрафах, налогах и коммунальных платежах. Для этого он использует NotificationService. Но есть несколько проблем:

Время ответа БД PostgreSql и MongoDb — от 30 мс до 200 мс (специально занижал производительность БД неправильными индексами и большой вложенностью Json. Также добавил по 1 млн записей в каждую БД)

Внутреннюю реализацию сервиса(MVC Tomcat) можно посмотреть здесь.

Тестовые запросы

Время ответа от сервиса входит в диапазон от 1 до 3 секунд.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Такое время ответа не устраивает как пингвинов, так и нас. Нужно разобраться в чем же проблема.

Блокирующие вызовы

Без нагрузки Tomcat, который по умолчанию используется в starter-web Спринга, создаёт 10 потоков http exec. При нагрузке же он может масштабироваться до 200 потоков. В моем примере томкат масштабировался примерно до 170 потоков при единовременной нагрузке в 1000 пользователей.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБез нагрузки webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоПод нагрузкой. Огромное количество потоков крадут друг у друга процессорное время. Нецелесообразное использование мощностей процессора

Нагрузочное тестирование показало, что 1000 одновременных запросов сервис обработал за 2 минуты 38 сек, количество ошибок составило 23.1 % от общего количества запросов при пропускной способности в 6.3 запроса в секунду.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСводная таблица по нагрузочному тестированию

Модель Tomcat основана на блокирующих вызовах. Когда поток обращается к БД или удаленному сервису, он блокируется и, пока не будет получен ответ, так и будет находится в заблокированном состоянии.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоКак ведет себя поток в стандартном MVC приложении на Tomcat

WEBFLUX Неблокирующие вызовы

Перейдем к другой реализации. Что за такой зверь WebFlux? Это микрофреймворк, который представляет полностью асинхронный и неблокирующий веб-стек, который позволяет обрабатывать большее количество одновременных запросов по сравнению с стандартным MVC.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Reactive streams

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Это стандартный способ асинхронной обработки в потоковом стиле. В него входят следующие интерфейсы: subscriber, publisher, subscription и processor.

Принцип работы reactive streams:

Subscriber подписывается на publisher(subscribe()), но общаться с publisher будет через subscription.

Subscription получает данные от publisher и отгружает их в подписчика (onNext(data)).

C помощью методов onError() и onComplete() Subscription принимает от Subscriber информацию о том, сколько данных он хочет получить от publisher через метод request(n). Старый добрый паттерн Наблюдатель, в лучшей реализации.

Реактивный сервер?

Да! Мы преобразуем наш сервис уведомления о штрафах в реактивное приложение. Для начала представим реактивную архитектуру:

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоАрхитектура реактивного приложения

Приложение состоит из 5 составляющих:

HTTP Server. В нашем случае Netty, так как WebFlux по умолчанию предоставляет данный сервер.

Реактивный адаптер. Интересно и зачем же здесь адаптер? Все очень просто. Netty и WebFlux не совместимы, поэтому здесь и нужен адаптер.

Репозиторий для коннекта с БД.

И последнее, все элементы архитектуры начинают общаться с помощью реактивного типа FLUX

Теперь подробнее про каждую часть.

NETTY

NETTY — асинхронная среда сетевых приложений, управляемая событиями. На входе у Netty в бесконечном цикле крутится поток. За счет каналов и селекторов он перенаправляет входящие запросы во входящие буферы и делегирует обработку запросов выделенному пулу асинхронных потоков.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Есть очередь событий и event loop, который их обрабатывает и делегирует пулу асинхронных потоков. В то же время происходит регистрация Callback-а. Он вызывается для отгрузки данных, после завершения обработки асинхронным пулом потоков.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Как же это выглядит в приложении? А вот как:

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Поток подписывается на определенное событие (выгрузка данных из БД), получает callback и идет работать дальше. После того, как данные будут готовы, поток вернется чтоб их забрать.

Reactive Adapter

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Вернемся к реактивному адаптеру. Я упомянул, что Netty и WebFlux несовместимы. Вот тут и появляется Reactor IPC.

Это расширение, позволяющее интегрироваться с различными платформами и системами. Когда запрос поступает на Netty, он обрабатывается ChannelOperations, затем вызывается цепочка вызовов, которая достигает Dispatcher handler, а затем запрос достигает контроллера.

Затем на основе publisher выстраивается поток, достигающий ChannelOperations. Следом в ChannelOperataions вызывается метод subscribe. Только в этот момент поток начинает свою работу.

Реактивные типы

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

К реактивным типам относятся Mono и Flux. Они имплементируют интерфейс publisher, т.е являются источниками данных.

Если нам нужно отгружать пользователю от 0 до N объектов используем FLUX

Если же нужно отгружать от 0 до 1 элементов используем MONO

Если мы ничего не хотим отгружать используем MONO

Publisher делят на два вида HOT и COLD.

Приведу аналогию: фильм, запущенный на Netflix с самого начала — это cold publisher, а стрим на twitch, в который мы ворвались на середине, — HOT. Cold publisher начинает отгружать данные, когда на него подписываются с самого начала, а Hot publisher отгружает данные тем, кто подписался с момента остановки отгрузки данных.

Элемент Processor импелементирует интерфейс subscriber и publisher, используется для обработки данных Mono или Flux для того, чтобы не обрывать стрим.

Теперь переведем сервис уведомления о штрафах из стандартного MVC в реактивный. Шкиперу должно понравиться.

Реактивное приложение

Начнем переводить наше приложение со стандартного MVC на WebFlux.

Чтобы перейти на WebFlux, нам нужно поменять зависимость с web на webflux. Мы получим готовый к использованию реактивный сервис.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Изменим контроллер так, чтобы он возвращал реактивный тип:

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

И проведем нагрузочное тестирование(1000 единовременных пользователей):

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБез нагрузки webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоПод нагрузкой

Без нагрузки создался один поток reactor-http-nio-1. Он работает постоянно. Под нагрузкой NETTY масштабировал количество потоков до 12. Мой ноутбук 6-ядерный, работает в 12 потоках, поэтому NETTY масштабировал на количество потоков процессора. Они также все время работают и не простаивают.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это1. Таблица MVC 2. таблица WebFlux

Нагрузочное тестирование показало: обработали быстрее, но получили большее количество ошибок. Непорядок.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

«Что и требовалось доказать, еще не много и нас взорвут» — говорит Шкипер.

Нужно разобраться, в чем причина такого количества ошибок.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоОсновная проблема — блокирующие вызовы к БД и удаленному сервису. webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоNetty делегирует обработку событий асинхронным потокам. Этих потоков критически мало по сравнению с Tomcat: 200 против 12

Если заблокируются все потоки в AsyncThreadPool, придется откидывать запросы, пока не освободится AsyncThreadPool.

Сперва сделаем БД реактивными. Для этого подключим реактивные драйверы на MongoDb и PostgreSql. Начнем с MongoDb.

Reactive Mongo Driver

MongoDb предоставляет свою реализацию reactive streams. Чтобы ее использовать, нам нужно поменять зависимости.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этобыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этостало

Теперь поменяем имплементацию репозитория и сменим ее на реактивную.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Теперь наш репозиторий реактивный. Вместо List возвращаем реактивный тип Flux. Он возвращает нам от 0 до N элементов. Реактивный драйвер MongoDb использует под капотом Netty, а в прошлых версиях asynchronous socket channel. Если хотите разобраться в этом глубже, переходите по ссылке.

Reactive Driver PostgreSql

Наступило время превратить нашу реляционная базу данных в реактивную.

Компания Pivotal релизнула spring-data-r2dbc (Декабрь 2019), что позволяет легко перейти на реактивный драйвер.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Изменения незначительные, репозиторий имплементирует r2dbc репозиторий и возвращает Flux.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Из интересных фактов: под капотом свою работу выполняет Netty. Для разбора закрепляю ссылку на r2dbc-driver.

WebClient

Перейдем к самому интересному — интеграции с удаленном сервисом. Вместо RestTemplate будем использовать более удобный и крутой WebClient.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Client возвращает реактивный тип Mono.

Reactive Service

Теперь приступим к изменению сервиса и контроллера, так как они должны возвращать тоже реактивные типы.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

Reactive Controller

Также меняем контроллер.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало

MediaType.APPLICATION_STREAM_JSON_VALUE дает понять контроллеру, что мы будем стримить данные пользователю пачками. То есть, как будет готов объект NotificationDTO, он сразу отгрузится пользователю, не дожидаясь остальных.

Как это выглядит в браузере:

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоДанные приходят не массивом, а пачками, по готовности webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоtransfer-encoding: chunked → позволяет надежно доставлять данные от сервера без необходимости заранее знать точный размер всего HTTP-сообщения. Как доказательство не присутствует Content-Length.

Теперь с пользователем общаемся с помощью событий. Каждое уведомление(NotificationDTO) и есть событие, которое нужно обработать. Пользователь не нужно ждать всего ответа.

Осталось поменять application.yaml.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБыло. Обратите внимание на Jdbc(блокирующий драйвер). webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоСтало. Поменял jdbc → на r2dbc. Для MongoDB настройки остались такими же

Нагрузочное тестирование реактивного приложения

Из нагрузочного тестирования видно, что мы смогли обработать 1000 одновременных запросов за 2:35, что быстрее MVC на 3 сек. Количество ошибок меньше на 9%. Реактивный сервис обработал большее количество запросов при меньшем количестве потоков. Заглянем в профилировщик.

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоБез нагрузки. Общее количество потоков составило 30(Netty). У MVC 34(Tomcat) webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что этоПод нагрузкой. Общее количество потоков составило 77(Netty). У MVC 221(Tomcat). Потоки работают на максимуме, используя всю мощность процессора.

Не напрягая зрение видно, что, помимо потоков приложения(reactor-htp-nio), появились еще два вида потоков:

reactor-tcp-nio — потоки для обслуживания r2dbc драйвера

nioEventLoopGroup — потоки реактивного драйвера MongoDB

Модернизированный сервис уведомления о штрафах

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

Новая архитектура позволяет делать выводы, что сервис отвечает требованиям Reactive Manifesto:

webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

    Responsive(отзывчивость) — с пользователем общаемся с помощью событий. Он получает все частями и работает с ними, даже если в процессе возникнет ошибка, пользователь получит часть данных.

    Elastic(Эластичность) — приложение использует минимальное количество потоков, они не простаивают и работают на максимум. Также применимо вертикальное масштабирование. Мощнее процессор, больше потоков.

    Message Driven — сервисы должны общаться с помощью событий. Реактивный сервис с помощью реактивных драйверов и WebClient общаются между собой именно так. То же и с пользователем: за счет MediaType.APPLICATION_STREAM_JSON_VALUE стримим событиями.

    Resilient(Устойчивость) — сервис должен адекватно реагировать на возникновение ошибок. В модернизированном приложении не делал никаких действий по устойчивости для чистоты эксперимента.

    Ну что, скажешь на это, Шкипер?

    webflux spring что это. Смотреть фото webflux spring что это. Смотреть картинку webflux spring что это. Картинка про webflux spring что это. Фото webflux spring что это

    Вопрос закрыт. Пингвины не справились с потоком штрафов, заказали судно и решили скрыться из страны. Миссия выполнена.

    Вывод

    WebFlux не про скорость обработки запроса, а про одновременное обслуживание большого количество запросов.

    Нужно правильно продумать архитектуру приложения, чтобы не было блокирующих соединений. Система должна отвечать требованиям Reactive Manifesto.

    Чтобы избавиться от блокировки бд и интеграции с медленными сервисами, используем реактивные драйверы и WebClient(R2dbc и Reactive MongoDb driver)

    WebFlux лучше всего использовать для большого количества одновременных запросов(Высоконагруженные системы)

    Если есть большое количество блокирующих соединений и малое количество одновременных запросов, лучше посмотреть в сторону стандартной реализаций MVC на tomcat

    Источник

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *