Основы реактивного программирования на Java. WebFlux + R2DBC
Вступление
С основами реактивного программирования мы разобрались в прошлой статье, теперь настало время подумать, для чего такой подход может быть применён.
Рассмотрим, пожалуй, самую популярную область IT - веб-разработку. Для стека на Java/Kotlin там часто применяются различные компоненты Spring Framework (Spring Data JPA, Spring MVC, драйвера баз данных).
Но с появлением пятой версии туда был встроен модуль под названием WebFlux. Этот микрофреймворк является альтернативой Spring MVC и отражает собой реактивный подход для написания веб-сервисов.
В основе WebFlux лежит уже известная нам библиотека Project Reactor, позволяющая легко запрограммировать неблокирующие потоки, работающие с вводом/выводом данных.
Spring MVC vs WebFlux
Основные отличия двух модулей лучше всего демонстрирует официальная документация.
Главным отличием является использование WebFlux-ом встроенного в Spring сервера Netty. Встроенные Tomcat и Jetty не подходят.
Также стоит отметить, что WebFlux поддерживает как обычные REST-контроллеры, применяемые в Spring MVC, так и RouterFunctions, использующие функциональный подход в написании кода.
А что по производительности?
Несмотря на отличие данных в различных источниках, а также результатах собственного исследования, на их основе можно однозначно сказать - WebFlux выигрывает у Spring MVC в количестве одновременно обрабатываемых запросов, начиная с нагрузки примерно в 300 пользователей. При предельной же загруженности сервера в реактивном режиме может одновременно обслуживаться в 2 раза больше пользователей.
R2DBC
Одной из самых долгих операций в веб-сервисах является, безусловно, запрос в базу данных. Здесь Spring тоже поддерживает реактивных подход в лице модуля Spring Data R2DBC (Reactive Relational Database Connectivity). В данный момент он находится на этапе развития, но основные поставщики реляционных баз данных (Oracle, PostgreSQL, MySQL) уже обеспечили его реактивными драйверами.
Главным недостатком R2DBC является отсутствие аналога Hibernate, что не позволяет с помощью Java описывать сложные связи между объектами или программно задать ограничение целостности таблиц.
Также существует много споров о том, является ли вообще R2DBC производительнее старого доброго JDBC. Чтобы их решить, нужно было написать собственный бенчмарк, в результате работы которого были получены такие результаты (использовался Apache JMeter, 200 одновременных пользователей, каждый по 500 запросов):
Пропускная способность оказалась примерно одинаковой для всех запросов, кроме получения первых 100 записей. Это обусловлено временем парсинга ответа БД с помощью R2DBC.