Почему Реактивное программирование
Монолитные приложения | Микросервисы |
Запуск на сервере приложений | Запуск в облаке |
Не поддерживает распределенные системы | Содержит распределенные системы |
Каким должно быть ваше приложение:
Шкала, основанная на нагрузке
Эффективное использование ресурсов
Время отклика должно быть быстрее
Модель, которую мы имеем, – это поток на запрос, где для каждого запроса может быть поток для этого запроса.
Обработка Одновременных Запросов
Управляется server.tomcat.max-потоки свойство
Значение по умолчанию – 200 подключений
Мы можем использовать application.properties или приложение.файл yml для переопределения значения
Каждый поток будет занимать некоторое количество памяти
Общий размер стека составляет 1 МБ
Чем больше размер пула потоков, тем выше потребление
При меньшем объеме доступной памяти наше приложение будет работать плохо.
Как это делается сегодня
Нагрузка сбалансирована с помощью горизонтального масштабирования и может быть достигнута с помощью некоторой оркестровки контейнеров
Но нам нужно создать несколько экземпляров, и это увеличит затраты для организации
Традиционные API-интерфейсы Rest
Отлично работает для многих случаев использования
Многие API будут в будущем также с таким же дизайном
Это не устарело
Также нет необходимости переводить традиционный Rest API на новую модель, так как у него есть свои преимущества
Как работает традиционный API Rest
// simple rest api end point @GetMapping("/getCatalog") public ResponseMessage getCatalog() { return movieFeignClient.listAllMovies(); }
API императивного стиля
- Подход сверху вниз
Блокирующий и синхронный
Блокировка означает, что когда пользователь отправляет запрос на сервер и данные должны быть извлечены из базы данных, поток обрабатывает запрос и выполняет вызов базы данных. До тех пор, пока ответ не будет получен, поток ничего не будет делать и будет находиться в состоянии блокировки, что неэффективно.
Синхронный означает, что клиенту необходимо дождаться возврата вызова API, прежде чем продолжить выполнение кода, что может привести к снижению производительности или проблемам, связанным с задержкой.
Так что мы можем сделать
- Нужно совершать звонки асинхронно, не блокируя
- У нас могут быть обратные вызовы и фьючерсы
Обратные вызовы:
Сложный
Нет возвращаемого значения
Код трудно читать и поддерживать
Ведет к Обратному вызову аду
Будущее:
Еще одна альтернатива написанию асинхронного кода на java
Возвращаемый экземпляр функции
Трудно составить несколько асинхронных операций
Завершаемое будущее:
Поддерживает API-интерфейсы функционального стиля
Простые в составлении асинхронные операции
Не очень подходит асинхронный вызов с несколькими элементами
Традиционный Rest API не имеет функции обратного давления, которая сообщает базе данных, предположим, если один из наших запросов отвечает огромным объемом данных, которые не нужны клиенту, тогда мы можем попросить базу данных замедлить процесс, например, создать противодавление.
В общем
Нам нужно разработать асинхронный и неблокирующий API
Отойти от модели потока по запросу
Используйте меньше потоков
Совместимость с обратным давлением
Реактивное программирование
Асинхронный и неблокирующий
Данные будут передаваться как Управляемые событиями/сообщениями поток
Функциональный код стиля
Противодавление на поток данных
Не ждать и блокировать
Поток данных как поток, управляемый событиями
Одно событие или сообщение для каждого результата из источника данных (БД, внешних служб и т.д.)
Одно событие или сообщение о завершении или ошибке
- Далее(пункт) -> События потока данных
- Неполный() -> Событие завершения/успеха
- onError() -> Событие ошибки
Функциональный Код Стиля
Легко работать с лямбдами
Аналогично API потоков
Спецификация реактивного пара
Спецификация или правила для реактивного потока
Издатель
Подписчик
Подписка
Процессор
Издатель
- Представляет источник данных
public interface Publisher{ public void subscribe(Subscriber super T> s); }
Подписчик
public interface Subscriber{ public void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); }
Подписка
public interface Subscription { public void request(long n); public void cancel(); }
Поток событий Издателя/Подписчика
Подписчик вызывает метод
subscribe()
и передает экземпляр Подписчика в качестве входных данных ИздателюИздатель подтверждает, отправляя подписку
Абонент предоставляет
запрос(n)
способ получения данныхИздатель создает
при следующем(данных)
событии для указанногоn
раз и при успешном завершении создаетнеполный()
событиеТаким образом, абонент предоставляет количество данных, которые говорят о функции обратного давления
Процессор
- Нравится комбинация как подписчика, так и издателя
public interface Processorextends Subscriber , Publisher { }
Реактивные библиотеки
RxJava
Реактор
Класс потока – JDK 9
Проектный реактор
активная зона реактора
Основная библиотека проектного реактора
Реализация спецификации реактивных потоков
поток и моно
поток представляет от 0 до n элементов
mono представляет от 0 до 1 элементов
Поток
Изображение взято из проекта Реактор
// flux Flux.just("Spring", "Spring Boot", "Reactive Spring Boot") .map(s -> s.concat("flux")) .subscribe(System.out::println);
Моно
Изображение взято из проекта Реактор
// mono Mono.just("Spring") .map(s -> s.concat("flux")) .subscribe(System.out::println);
Я включил некоторые практические примеры flux и mono в репозиторий github, и еще есть примеры, которые будут добавлены и будут обновлены. Пожалуйста, посмотрите и прокомментируйте любые ошибки, которые я допустил и которые необходимо исправить.
Рохитв07/Реактивная пружина
Реактивное программирование весной
Реактивное программирование весной
Почему Реактивное программирование
Монолитные приложения | Микросервисы |
Запуск на сервере приложений | Запуск в облаке |
Не поддерживает распределенные системы | Содержит распределенные системы |
Каким должно быть ваше приложение:
Шкала, основанная на нагрузке
Эффективное использование ресурсов
Время отклика должно быть быстрее
Модель, которую мы имеем, – это поток на запрос, где для каждого запроса может быть поток для этого запроса.
Обработка Одновременных Запросов
Управляется server.tomcat.max-потоки свойство
Значение по умолчанию – 200 подключений
Мы можем использовать application.properties или приложение.файл yml для переопределения значения
Каждый поток будет занимать некоторое количество памяти
Общий размер стека составляет 1 МБ
Чем больше размер пула потоков, тем выше потребление
При меньшем объеме доступной памяти наше приложение будет работать плохо.
Как это делается сегодня
Нагрузка сбалансирована с помощью горизонтального масштабирования и может быть достигнута с помощью некоторой оркестровки контейнеров
Но нам нужно создавать…
Оригинал: “https://dev.to/rohithv07/introduction-to-reactive-spring-40nm”