Spring in Action Covers Spring 5-1--11 — страница 51 из 63

dependency>

org.springframework.boot

spring-boot-starter-web

В то время как это делает RestTemplate доступным в classpath, оно также запускает автоконфигурирование для Spring MVC. В качестве автономного потока Spring Integration приложению не требуется Spring MVC или даже встроенный Tomcat, который обеспечивает автоконфигурация. Поэтому вам следует отключить автоконфигурирование Spring MVC с помощью следующей записи в application.yml:

spring:

    main:

        web-application-type: none

Свойство spring.main.web-application-type может быть установлено в servlet, reactive или none. Когда Spring MVC находится в classpath, автоконфигурация устанавливает его значение в servlet. Но здесь вы переопределяете его на none, чтобы Spring MVC и Tomcat не были автоматически сконфигурированы. (Мы поговорим подробнее о том, что означает, что приложение является reactive веб-приложением в главе 11.)

ИТОГ:

-Spring Integration позволяет определять потоки, через которые данные могут обрабатываться при их поступлении в приложение или на выходе из него.

-Интеграционные потоки могут быть определены в XML, Java или с использованием краткого стиля конфигурации Java DSL.

-Шлюзы сообщений и адаптеры каналов действуют как точки входа и выхода интеграционного потока.

-Сообщения могут быть преобразованы, разделены, агрегированы, направлены и обработаны активаторами службы в ходе потока.

-Каналы сообщений соединяют компоненты потока интеграции.

Spring in Action Covers Spring 5.0 перевод на русский. Глава 10

РАЗДЕЛ 3

Реактивный Spring

В разделе 3, мы рассмотрим новую замечательную поддержку реактивного программирования в Spring. В главе 10 обсуждаются основы реактивного программирования с Project Reactor, библиотекой реактивного программирования, которая лежит в основе реактивных функций Spring 5. Затем мы рассмотрим некоторые из наиболее полезных реактивных операций Reactor. В главе 11 мы вернемся к разработке REST API, представив Spring WebFlux, новую веб-инфраструктуру, которая позаимствовала многое из Spring MVC и предлагает новую реактивную модель для веб-разработки. В главе 12 завершается третья часть, в которой описывается постоянное сохранение реактивных данных с помощью Spring Data для чтения и записи данных в базы данных Cassandra и Mongo.

10. Знакомство с Reactor

В этой главе рассматривается

-Понимание реактивного программирования

-Project Reacto

-Реактивная работа с данными

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

Теперь предположим, что если после оплаты вашей подписки прошло несколько дней, и издания не были доставлены. Проходит еще несколько дней, и вы звоните в отдел продаж, чтобы узнать, почему вы еще не получили ежедневную газету. Представьте свой сюрприз, если они объяснят: «Вы заплатили за целый год газет. Год еще не закончен. Вы обязательно получите их все, как только будет готово полное годовое издание газет».

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

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

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

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

В этой главе мы временно отойдем от приложения Taco Cloud, чтобы изучить Project Reactor. Reactor - это библиотека для реактивного программирования, которая является частью семейства проектов Spring. И поскольку он служит основой поддержки реактивного программирования в Spring 5, важно, чтобы вы поняли Reactor, прежде чем мы рассмотрим создание реактивных контроллеров и репозиториев с помощью Spring. Прежде чем мы начнем работать с Reactor, давайте быстро рассмотрим основы реактивного программирования.

10.1 Понимание реактивного программирования

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

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

Если вы похожи на меня и многих разработчиков, вы режете свои программные зубы императивным программированием. Есть хороший шанс, что большинство (или весь) код, который вы пишете сегодня, по-прежнему является императивным по своей природе. Императивное программирование достаточно интуитивно, что молодые студенты с легкостью изучают его в своих школьных программах STEM, и оно достаточно мощное, чтобы составлять основную часть кода, который используется во многих крупнейших предприятия.

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

Во время выполнения задачи, особенно если это задача I/O, такая как запись данных в базу данных или выборка данных с удаленного сервера, поток, вызвавший эту задачу, блокируется и не может ничего сделать, пока задача не завершится. Проще говоря, заблокированные потоки расточительны.

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

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

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

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

-Садовый шланг несет свою полезную нагрузку в виде потока воды, который течет от крана к соплу. Емкость садового шланга может быть конечной в любой момент времени, но она неограничена в течение водного боя. Пока вода поступает в шланг из крана, она будет продолжать течь через шланг и распыляться из сопла. Тот же садовый шланг легко масштабируется, чтобы замочить столько друзей, сколько вы хотите.

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

10.1.1 Определение реактивных потоков

Reactive Streams - инициатива, начатая в конце 2013 года инженерами из Netflix, Lightbend и Pivotal (компания, стоящая за Spring). Reactive Streams стремится обеспечить стандарт для асинхронной обработки потока с неблокирующим обратным давлением (backpressure).

Мы уже затронули асинхронную черту реактивного программирования; это то, что позволяет нам выполнять задачи параллельно для достижения большей масштабируемости. Противодавление - это средство, с помощью которого потребители данных могут избежать перегруженности слишком быстрым источником данных, устанавливая ограничения на то, сколько они готовы обработать.

Java Streams vs. Reactive Streams