Reactive Streams выпускает первую стабильную версию для JVM
Reactive Streams выпускает первую стабильную версию для JVM
5 минут
Перевод статьи:
АБРАХАМ МАРИН ПЕРЕС
INFOQ | JUN 01, 2015
После более чем года работы на чертежной доске Reactive Streams выпустила версию 1.0 своего API для нескольких различных платформ, в том числе Java. Эта библиотека не будет добавлять возможности, которые ранее не были доступны, но предоставит общую структуру для стандартизации шаблонов.
Когда Reactive Streams начали свою работу, следуя пути, установленному Reactive Manifesto, они указали, что их цель - предоставить «стандарт для асинхронной обработки потока с неблокирующим обратным давлением». Однако главная проблема заключалась не в том, чтобы найти решение, поскольку их уже было несколько. Задача заключалась в том, чтобы объединить различные существующие шаблоны в общий, чтобы максимизировать взаимодействие. Точнее, целью Reactive Streams было «найти минимальный набор интерфейсов, методов и протоколов, которые будут описывать необходимые операции и сущности для достижения цели - асинхронные потоки данных с неблокирующим обратным давлением».
Концепция «обратного давления» является ключевой. Когда асинхронный потребитель подписывается на получение сообщений от производителя, он обычно предоставляет некоторую форму метода обратного вызова, который будет вызываться всякий раз, когда новое сообщение становится доступным. Если производитель отправляет сообщения с более высокой скоростью, чем может обработать потребитель, потребитель может быть вынужден захватить все большее количество ресурсов и потенциально аварийно завершить работу. Чтобы предотвратить это, необходим механизм, с помощью которого потребители могут уведомлять производителей о необходимости снижения скорости передачи сообщений. Затем производители могут использовать одну из нескольких стратегий для достижения этой цели. Этот механизм называется обратным давлением.
Блокировать обратное давление легко. Если, например, производитель и потребитель работают в одном потоке, выполнение одного блокирует выполнение другого. Это означает, что пока выполняется потребитель, производитель не может отправлять какие-либо новые сообщения, и поэтому возникает естественный способ сбалансировать ввод и вывод. Однако есть сценарии, в которых блокирование обратного давления нежелательно (например, когда у производителя несколько потребителей, не все из них используют сообщения с одинаковой скоростью) или просто недостижимо (например, когда потребитель и производитель работают в разных средах). В этих случаях необходимо, чтобы механизм противодавления работал без блокировки.
Способ достижения неблокирующего обратного давления состоит в переходе от стратегии push, при которой производитель отправляет сообщения потребителю, как только они становятся доступными, к стратегии получения сообщений, когда потребитель запрашивает некоторое количество сообщений у производителя, и это отправляет только до этой суммы, ожидая дальнейших запросов перед отправкой. Это стратегия, выбранная Reactive Streams, как можно понять, проанализировав интерфейсы.
Стоит отметить, что неблокирующее обратное давление уже было в некоторой степени доступно в Java 8 через недавно представленный API java.util.Streams. Как пояснил Рауль-Габриэль Урма, соавтор книги «Java 8 in Action», новые потоки в Java 8 вместе со всеми операциями, которые могут быть выполнены с ними, уже следуют вышеупомянутой стратегии извлечения, таким образом обеспечивая форму не -блокировка обратного давления. Тем не менее, это не является несовместимым с определением стандарта для реактивных систем, на самом деле, уже ведется работа над тем, чтобы сделать Java-реализацию Reactive Streams частью Java 9: Дуг Ли, лидер JSR 166, который добавил в Java утилиты параллелизма. , предложил новый класс Flow, который будет включать интерфейсы, которые в настоящее время предоставляются Reactive Streams. Дуг обосновал свое предложение тем, что «не существует единого, наиболее удобного асинхронного / параллельного API. CompletableFuture / CompletionStage лучше всего поддерживает программирование в стиле продолжения для фьючерсов, а java.util.stream лучше всего поддерживает (многоэтапные, возможно, параллельные) операции в стиле «вытягивания» над элементами коллекций. До сих пор одной отсутствующей категорией были операции в стиле «push» над элементами, когда они становятся доступными из активного источника ».
Возможные приложения
TypeSafe, один из основных разработчиков Reactive Streams, указал во время публичного вебинара на некоторые из наиболее распространенных приложений этой технологии: массовая передача данных, источники данных в реальном времени, пакетная обработка больших наборов данных, мониторинг и аналитика. Однако наиболее интересные и многообещающие приложения Reactive Streams могут исходить из области распределенных вычислений.
Говоря о распределенных вычислениях, можно выделить две основные парадигмы: радиальная парадигма, когда центральная система распределяет рабочую нагрузку между узловыми компьютерами, а затем собирает результаты, и ячеистая модель, в которой нет центрального объекта, а есть только несколько потенциально неоднородных подключенных устройств. друг другу. Хотя оба типа распределенных вычислительных сетей могут выиграть от Reactive Streams, это второй тип, который может получить больше всего.
Радиальные сети, как правило, планируются и поэтому тщательно проектируются и контролируются. Mesh-сети, напротив, имеют тенденцию формироваться спонтанно при подключении устройств более низкого уровня, таких как сеть датчиков или мобильные телефоны людей. Из-за неотъемлемой непредсказуемости ячеистых сетей отказоустойчивость, обеспечиваемая Reactive Streams, является ключом к предотвращению краха сети. Мы поговорили с Хосе Луисом Фернандес-Маркесом, ведущим разработчиком проекта SAPERE в Институте науки об услугах Женевского университета (Швейцария). Хосе Луис рассказал о пяти основных группах приложений, в которых ячеистые сети потенциально могут извлечь выгоду из Reactive Streams:
Массивные скопления людей и/или устройств, где традиционные антенны перегружены и связь невозможна, например, пробки, музыкальные фестивали и другие мероприятия. В этих ситуациях мобильные телефоны могут обеспечивать связь, создавая спонтанную ячеистую сеть, в которой только некоторые устройства будут взаимодействовать с главными антеннами, а остальные будут устанавливать связь косвенно через спонтанную сеть.
Сценарии, когда базовая инфраструктура связи недоступна, например, после стихийных бедствий или в слаборазвитых районах. Связь может стать возможной за счет создания ячеистой сети с любыми доступными устройствами.
Приложения со сверхмалой задержкой, такие как связь между автомобилями или информация о зависании. Транспортные средства могут сообщать друг другу о авариях, образовании льда и других угрозах при условии, что между ними была создана сеть.
Локализованные данные, представляющие локальный интерес, в частности, когда данные представляют интерес только в той же области, где они производятся, например, данные о трафике в реальном времени. Поскольку пользователям города A вряд ли понадобятся данные о трафике в реальном времени для города B, нет необходимости устанавливать центральные серверы для сопоставления и воспроизведения этих данных; вместо этого пользователи в городе A могут обмениваться этой информацией через ячеистую сеть.
Конфиденциальность. Ячеистая сеть может использоваться для обеспечения обмена данными без прохождения через центральный (и потенциально цензурирующий) объект. Такие приложения, как FireChat, уже следуют этому шаблону.
Все вышеперечисленное и, возможно, даже больше, приведет к созданию сети с непредсказуемым трафиком с непредсказуемыми узкими местами. Без соответствующего механизма для управления коммуникациями узлы могут легко перегрузиться и упасть, что потенциально может повлиять на саму сеть. Хосе Луис считает, что Reactive Streams может стать частью этого механизма.