Событийная архитектура: что менеджеру нужно знать до принятия решения
События и очереди сообщений решают реальные проблемы координации между сервисами. Они также вносят сложность, которую легко недооценить на уровне плана проекта.
Если вы читали архитектурный контент последние несколько лет, вы видели событийно-ориентированную архитектуру как естественного преемника REST API и синхронных вызовов между сервисами. Идея в том, что сервисы общаются, публикуя события в брокер сообщений - чаще всего Kafka - а другие сервисы потребляют эти события независимо, без необходимости продюсеру знать, кто слушает.
Это решает реальные проблемы. Но и вносит другой набор проблем, которые менее заметны на ранних стадиях проекта.
Что это реально решает
Проблема, которую событийная архитектура решает наиболее чисто - это тесная связанность сервисов. Когда сервис A вызывает сервис B синхронно, A должен ждать ответа от B, и если B медленный или упал, A ощущает это напрямую. С событиями A публикует и движется дальше. B обрабатывает, когда готов.
Это важно при масштабировании, и важно когда сервисы принадлежат разным командам с разными циклами выпуска. Сервис логистики и сервис выставления счетов могут развиваться независимо, если общаются через общий журнал событий, а не через прямые API-вызовы.
Второе преимущество - аудитируемость. Журнал событий - это запись о том, что произошло и когда. Для некоторых доменов - финансовые транзакции, движения запасов, изменения статуса заказа - это реально ценно.
Что это усложняет
Первое, что усложняется - это отладка. Когда в синхронной системе что-то идёт не так, вы трассируете стек вызовов. Когда в событийной системе теряется сообщение, вы отслеживаете его через журнал событий в нескольких сервисах с потенциально разными метками времени и хранилищами. Это возможно, но требует инструментария и дисциплины, которые многие команды недооценивают.
Второе - это согласованность. При синхронном вызове результат либо зафиксирован, либо нет - вы получаете ответ. С событиями у вас конечная согласованность. Сервис заказов опубликовал событие. Сервис инвентаря уже обработал его? А система управления складом? Если пользователь проверяет статус заказа через тридцать секунд после его оформления, ответ может зависеть от того, какой сервис успел обработать событие.
Для одних доменов это нормально. Для других - существенное осложнение.
Третье - операционная сложность. Брокер сообщений - это система, которую нужно запускать, мониторить, масштабировать и делать резервные копии. Kafka мощный и непростой в эксплуатации. Команды, с которыми я видел проблемы при событийной архитектуре - это чаще всего те, кто выбрал её до того, как у них была операционная зрелость для надёжного запуска этой инфраструктуры.
Вопросы, которые стоит задать перед выбором
Прежде чем принять событийный подход, я задаю вопросы:
- Какую конкретную проблему связанности вы решаете? Это реальная проблема при вашем текущем масштабе или прогнозируемая?
- Есть ли у команды опыт эксплуатации брокера сообщений в продакшне?
- Терпимы ли затронутые домены к конечной согласованности, или они требуют синхронного подтверждения?
- Какова цена задержанного или потерянного сообщения в вашем конкретном контексте?
- Стоит ли аудитируемость и возможность воспроизведения событий усложнения, или более простое решение закроет требование?
Практическая формулировка
Событийная архитектура не лучше и не хуже синхронной интеграции в абстракции. Это правильный инструмент для конкретных задач: высокопроизводительная несвязанная обработка, требования к журналу аудита, интеграция между системами с очень разными операционными характеристиками.
Если вы компания из пятидесяти человек с двумя бэкенд-инженерами, операционные накладные расходы на Kafka могут не оправдать задачу координации, которая у вас реально стоит. Хорошо спроектированный REST API с чётким владением и задокументированным контрактом решает большую часть того, что нужно малым и средним компаниям, и стоит значительно дешевле в эксплуатации.
Архитектурное решение должно следовать за задачей, а не за трендом.