Реактивная архитектура на уровне кода

preview

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

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

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

Сегодня мы поговорим о стратегиях обработки ошибок на уровне кода, посмотрим что из себя представляют события и сообщения, поговорим про два конкретных шаблона Observer и Pub/Sub

Стратегия обработки ошибок

Duration: 10

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

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

Четвертый пункт определяет требование к проектированию кода и по возможности контролируется тестами.

Основа стратегии - "устойчивость к сбоям" вместо "недопущение сбоев". Это значит, что мы проектируя код должны рассмотреть отдельную "не тупиковую" ветку поведения для сбойной ситуации. Здесь можно активно использовать null-object, а так же "пустые события", либо "откат транзакции".

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

Отдельные аспекты проектирования в целях обеспечения мониторинга и поиска корневой причины:

  • Логирование
  • Fail Fast

Механизмы реактивного поведения

Duration: 5

Программные: - Процессы - поддержка множества процессов на уровне системы или языка; - Зеленые потоки - возможность реализации "леговесных" потоков; - EventLoop - возможность реализовать в рамках одного потока асинхронного поведения; - Промисы - отложенная обработка событий;

Формальные: - Теория взаимодействующих процессов - возможность формального описания взаимодействия параллельных систем как единого процесса; - Модель Акторов - математическая модель параллельных вычислений.

События и сообщения

Duration: 10

В зависимости от того где выполняется код возможно использовать одну из двух моделей поведения программы:

  • внутри одного процесса (событийно-ориентированная);
  • распределенная или межпроцессная (на основе сообщений).

Если программа функционирует в рамках одного процесса, то поведение программы может рассматриваться как набор событий, каждое из которых имеет связанный обработчик события. Таким образом программа может запускать обработчик события при наступлении события (обычно действий пользователя или результатов обработки других событий).

Событие характеризуется:

  • Формат: двоичный или текстовый;
  • Структура: прямое использование ОЗУ;
  • Поведение: статическое или динамическое;
  • Обработка: через внутренний callback;

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

В случае распределенных систем взаимодействие осуществляется на основе механизмов обмена сообщениями, при этом "события" преобразуются в соответствующие сообщения.

Сообщения характеризуются:

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

Взаимодействие на базе событий и сообщений может носить как синхронный (явно ожидаем подтверждения), так и асинхронный характер. Но события - это всегда жесткое зацепление.

Поток данных

Duration: 10

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

  • Точка - точка;
  • Точка - поток;
  • Поток - точка;

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

Основные элементы потока данных: - сообщения / сериализованные события; - типы сообщений / каналы;

Основные способы передачи: - Шины; - Очереди.

Реактивное поведение - это поведение которое характеризуется наличием двух свойств системы: - Поток данных; - Распространение реакции на все зависимые компоненты.

Как связать ООП и реактивную архитектуру

Duration: 5

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

Рассмтрим три шаблона, которые могут быть доработаны до реактивной парадигмы: - Pub/Sub - Observer

Шаблон Mediator => Pub/Sub

Duration: 10

Pub/Sub

Шаблон Observer

Duration: 5

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

Observer

Разница между Pub/Sub и Observer

Duration: 5

Часто задают вопрос в чем разница между Pub/Sub и Observer. Разница есть как между двумя этими шаблона в принципе, так и в реализации для реактивных приложений.

В контексте реактивной архитектуры нужно отметить, что Pub/Sub и Observer - работают с событийной архитектурой, а реактивное поведение достигается с помощью "сообщений", которые берутся из "потока данных".

Различия: - Observer "знает" о своих подписчиках напрямую, это создает сильное зацепление; - Observer сразу генерирует "событие", т.е. по факту вызывает callback; - Pub/Sub разделяет "публикацию события" и его запуск - вызов callback; - Pub/Sub "знает" только о топике и не знает реальных подписчиках;