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