конспект курса «Lightbend Akka Streams for Java - Professional» by Lightbend Academy

Введение

Stream - это последовательность данных, состоящая из отдельных элементов. Обычно размер stream’а заранее неизвестен, а размер данных, проходящих через stream, слишком велик для размещения в памяти. Примеры: онлайн видео поток, данные фитнес-браслета.

Reactive Streams - это инициатива по созданию стандарта асинхронной потоковой обработки данных с обеспечением неблокирующего контроля интенсивности их поступления (back pressure). Готовность к получению новой порции данных, при этом, исходит от потребителя данных (subscriber) к поставщику (publisher). Основная цель данной инициативы - обеспечение взаимодействия между различными (но соответствующими стандарту) реализациями.

Стандартными компонентами Reactive Streams в Java являются:

Модуль Akka Streams предоставляет высокоуровневое API для работы со stream’ами, а интерфейсы Reactive Streams используются только в низкоуровневом API.

Схема линейного потока данных:

{Внешний источник данных} --> [Source] --> [Flow] --> [Sink] --> {Внешний потребитель данных}

Пример простого stream’а:

akka.actor.ActorSystem actorSystem = akka.actor.ActorSystem.create("system");
akka.stream.Materializer materializer = akka.stream.Materializer.createMaterializer(actorSystem);

akka.stream.javadsl.Source.from(List.of(1, 2, 3, 4))
    .via(akka.stream.javadsl.Flow.of(Integer.class).map(elem -> elem * 2))
    .to(akka.stream.javadsl.Sink.foreach(System.out::println))
    .run(materializer);

Sources

Source - это вход в stream.

Source публикует данные только по запросу от последующих стадий.

Некоторые типы Source‘ов:

Sinks

Sink - это выход из stream.

Sink управляет поступлением новых данных.

Некоторые типы Sink‘ов:

Flows

Flow - используется для манипулирования данными идущими от Source к Sink.

Некоторые типы Flow:

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

Runnable Graphs

RunnableGraph - представляет собой соединенные друг с другом Source, Flow (необязательно) и Sink.

Материализация (materialization) заключается в выделение необходимых ресурсов для запуска stream’а, и выполняется с помощью так называемых терминальных операций, таких как run() и runWith().

Результатом материализации stream’а является материализованное значение которое предоставляет возможность взаимодействия с ним.

Отказоустойчивость

Отказоустойчивость в Akka Streams реализована в виде стратегий, которые настраиваются с помощью атрибутов RunnableGraph‘а (или отдельных стадий).

Для завершения, в случае ошибки, stream’а с определенным значением используется метод recover.

Графы

Объединения и разветвления stream’ов реализованы в виде соединителей (junctions).

Для создания сложных графов Akka Streams предоставляет Graph DSL.

Fusing

Все операторы Akka Streams, по умолчанию, сливаются (fusing) вместе и выполняются последовательно. Т.е. каждый элемент должен пройти все этапы перед тем как в stream поступит новый элемент.

Данное поведение настраивается параметром akka.stream.materializer.auto-fusing.

Для асинхронного выполнения любой стадии используется метод async().

Следует учитывать, что асинхронное выполнение стадии в stream приведет к накладным расходам в виде дополнительных акторов (и их mailbox’ов) и буферов.