m@ksim.pro
К списку статей
ИТ 3 мин чтения

Событийно-ориентированная архитектура: что реально даёт разделение сервисов

Понятное объяснение событийных паттернов для собственников и менеджеров - какие проблемы они решают, какие новые вводят, и когда компромисс имеет смысл.

Когда программное обеспечение компании растёт несколько лет, оно обычно достигает точки, где изменение чего-либо в одной части системы требует знания того, что это сломает где-то ещё. Команды начинают координировать релизы, потому что сервис A вызывает сервис B напрямую, и B нужно обновить до того, как A можно задеплоить. Тестирование дорожает, потому что вся цепочка должна быть запущена.

Событийно-ориентированная архитектура (EDA) - один из главных инструментов для решения этой проблемы. И одновременно один из главных источников случайной сложности в системах, которые внедрили её без чёткого понимания компромиссов. Этот пост - попытка честного инвентаря.

Основная идея

В синхронной системе запрос-ответ сервис A вызывает сервис B и ждёт ответа. A знает о B; A связан с интерфейсом B и его доступностью.

В событийно-ориентированной системе сервис A публикует событие - «заказ был оформлен», «платёж получен», «пользователь удалён» - в брокер сообщений. Сервис B (и сервис C, и сервис D) подписываются на интересующие их события и реагируют на них асинхронно. A не знает, кто слушает. A не ждёт.

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

Что это даёт

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

Устойчивость к отказам downstream. Если сервис B недоступен, события накапливаются в брокере. Когда B возвращается, он обрабатывает накопившееся. Сервис A никогда не видел сбоя.

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

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

Что это не решает

EDA вводит собственную категорию сложности, которую команды часто недооценивают:

Eventual consistency сложнее осмыслить. В синхронной системе после успешного вызова вы знаете, что состояние downstream было обновлено. В событийно-ориентированной системе вы знаете, что событие было опубликовано - вы не знаете, когда (или, в случае сбоев, было ли) оно обработано. UI, которому нужно отражать текущее состояние, должен явно это обрабатывать.

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

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

Эволюция схем. У событий есть схемы. Когда схема меняется, все потребители нужно обновить - или нужна стратегия версионирования. Это реальная координационная стоимость.

Когда компромисс имеет смысл

EDA стоит сложности, когда:

  • Есть несколько независимых команд, которые иначе блокировались бы тесным зацеплением.
  • Есть чёткая, стабильная семантика событий - бизнес-факты, значимые независимо от того, кто их потребляет.
  • Есть операционная зрелость для управления брокером сообщений, мониторинга лага потребителей и трейсинга потоков событий.
  • Моделируемые процессы действительно асинхронны - уведомления, отчётность, аудит, фоновое обогащение.

Не стоит, когда:

  • Система достаточно мала, чтобы прямые вызовы были обслуживаемы.
  • «Разделение» теоретическое - на практике одна команда владеет всеми сервисами.
  • Ответ на событие всегда нужен до возврата к пользователю (это синхронное взаимодействие, переодетое в события).

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

К списку статей
Контакт

Если эта статья отозвалась - напишите. Я отвечаю лично.

Telegram