Понимание архитектурных шаблонов, основанных на событиях: Pub / Sub, Cqrs и многое другое
Архитектура, управляемая событиями (EDA) стала основополагающей парадигмой проектирования для построения распределенных, масштабируемых и отзывчивых систем. Вместо того, чтобы полагаться на тесную связь между компонентами посредством прямых вызовов методов или удаленных вызовов процедур, EDA переносит связь на производство, обнаружение и потребление событий. Событие - это значимое изменение состояния - то, что произошло, что другие части системы могут заботиться о. Это разделение позволяет каждой службе развиваться независимо, масштабироваться самостоятельно и реагировать на изменения по мере их возникновения. Понимание основных моделей EDA - таких как Публикация / Подписка (Pub / Sub), Сегрегация ответственности командных запросов (CQRS) и Искажение событий - имеет важное значение для любого разработчика или архитектора, стремящегося создать современные облачные приложения, которые могут обрабатывать потоки данных в реальном времени и непредсказуемые модели нагрузки.
Что такое событийно-управляемая архитектура?
По своей сути, EDA рассматривает события как первоклассных граждан. Событие - это неизменная запись того, что произошло в прошлом - например, OrderPlaced , UserRegistered или PaymentFailed . Компоненты, известные как производители событий, генерируют эти события, не зная, какие компоненты будут их потреблять. Потребители событий подписываются на конкретные типы событий и реагируют соответствующим образом. Брокер событий, такой как Apache Kafka, RabbitMQ или AWS EventBridge, сидит между производителями и потребителями, обеспечивая надежную доставку, настойчивость и порядок семантики, когда это необходимо.
Эта архитектура контрастирует с традиционными моделями синхронного запроса-ответа, где сервис напрямую вызывает другую услугу и ждет ответа. Синхронная связь создает плотную связь: если служба нисходящего потока медленная или недоступная, абонент блокируется. С EDA производители запускают события и немедленно продолжают свою работу. Потребители обрабатывают события асинхронно, часто с помощью собственной политики масштабирования. Эта модель не только повышает устойчивость системы, но и позволяет в реальном времени передавать потоки, проверяемость и возможность добавлять новых потребителей без изменения существующего кода.
EDA особенно мощна в экосистемах микросервисов, средах полиглотов и любых доменах, которые требуют высокой пропускной способности, низкой задержки или рабочих процессов, связанных с событиями, таких как обработка заказов, прием данных IoT и обнаружение мошенничества.
Основные шаблоны в Event-Driven архитектуре
Публикация/подписка (Pub/Sub)
Паттерн Pub/Subscribe (Pub/Sub) является самым простым и широко распространенным шаблоном EDA. В этой модели издатели выделяют события на тему или канал. Абоненты регистрируют интерес к этим темам и получают все опубликованные им события. Брокер обрабатывает вентиляцию, гарантии доставки и фильтрацию. Издатели и подписчики не знают друг друга — в этом суть свободной связи.
Например, рассмотрим платформу электронной коммерции. Когда клиент размещает заказ, служба заказа публикует событие OrderPlaced на тему «заказов». Несколько подписчиков подбирают это событие:
- Служба инвентаризации вычитает запасы.
- Платежная услуга взимает плату с клиента.
- Служба уведомлений отправляет подтверждение по электронной почте.
- Аналитический сервис записывает событие для отчетности.
Каждый абонент обрабатывает событие самостоятельно и в своем темпе. Если служба уведомлений медленная, это не влияет на службу заказа или службу инвентаризации. Этот шаблон, естественно, поддерживает масштабирование; вы можете добавить больше экземпляров службы инвентаризации для обработки повышенной нагрузки, не касаясь других компонентов.
Популярные инструменты для реализации Pub/Sub включают Apache Kafka, который обеспечивает высокую пропускную способность, постоянные и воспроизводимые потоки событий; RabbitMQ с его маршрутизацией и обменами темами; и облачные сервисы, такие как AWS EventBridge, который предлагает реестр схем и фильтрацию. Выбор правильного брокера зависит от вашей долговечности, заказа и требований к пропускной способности.
Разделение ответственности командных запросов (CQRS)
Разделение ответственности командных запросов (CQRS) - это шаблон, который отделяет операции записи (команды) от операций чтения (запросы) в разные модели. В традиционных системах CRUD одна и та же модель данных используется как для обновлений, так и для считывания, что может привести к проблемам производительности, когда рабочая нагрузка несбалансирована - например, сложный путь записи, который также должен обслуживать запросы чтения, оптимизированные для другой схемы.
В системе на основе CQRS команда, такая как PlaceOrder, запускает модель записи, которая проверяет бизнес-правила и производит событие (например, OrderCreated. Это событие обновляет базу данных на стороне записи. Между тем, отдельная модель чтения — часто денормализованная, оптимизированная под запросы база данных — слушает одно и то же событие и обновляет свои собственные таблицы. Запросы попадают в модель чтения, которая может быть масштабирована независимо или даже использовать совершенно другую технологию (например, Elasticsearch для поиска, Redis для кэширования). Модель записи и модель чтения в конечном итоге согласованы.
Преимущества CQRS включают в себя:
- Перформанс: Нагрузки на чтение могут обслуживаться специализированными магазинами без претензий со стороны записей.
- Безопасность: Вы можете предоставлять команды и запросы различным аудиториям; например, команда может потребовать аутентификации, в то время как публичный запрос читается только для чтения.
- Масштабируемость: Считывающие и записывающие стороны могут масштабироваться независимо на разных аппаратных средствах или кластерах.
- Гибкость: Вы можете развить схему чтения, не влияя на логику командной стороны.
Однако CQRS добавляет сложность, поскольку он вносит возможную согласованность и часто требует синхронизации, управляемой событиями, между двумя сторонами. Он естественным образом сочетается с Event Sourcing, где сторона записи хранит последовательность событий, а не снимок текущего состояния. Статья Мартина Фаулера о CQRS является отличным ресурсом для понимания компромиссов шаблона.
Источник событий
Источник событий - это шаблон, в котором изменения состояния хранятся в виде хронологической последовательности событий, а не в виде снимка текущего состояния. Вместо того, чтобы перезаписывать запись в базе данных, каждая мутация генерирует новое событие, добавленное к журналу событий. Текущее состояние может быть получено путем повторения всех событий с самого начала - или с помощью снимков с интервалами для ускорения восстановления.
Event Sourceing предоставляет несколько мощных преимуществ:
- Полный контрольный след: Каждое изменение записывается, что позволяет вам увидеть полную историю организации.
- Отладка и отладка: Вы можете воспроизводить события в среде разработки для воспроизведения ошибок или тестирования новой бизнес-логики.
- Временные запросы: Вы можете спросить, каким было состояние в любой момент времени.
- Простота принятия CQRS: Магазин событий служит моделью записи, а модели чтения могут подписываться на события для обновлений в реальном времени.
Основной компромисс - это увеличение объема и сложности. Запрос непосредственно в магазине событий часто неэффективен, поэтому вы обычно создаете модели чтения (Проекции), которые материализуют взгляды. Искажение событий распространено в таких областях, как финансовый учет, банковское дело и совместное редактирование документов, где каждое изменение должно быть записано.
Event Streaming (Стриминг)
Потоковое событие рассматривает события как непрерывный, неограниченный поток данных. Этот паттерн используется для анализа, мониторинга и интеграции данных в реальном времени в масштабе. В потоковом событии события поступают от нескольких производителей и обрабатываются в режиме реального времени потоковыми процессорами, которые фильтруют, агрегируют и преобразуют данные. Обработанные результаты могут храниться, отправляться в другой поток или использоваться для запуска действий по потоку.
Apache Kafka является фактическим стандартом для потокового вещания событий. Он хранит события в неизменяемых журналах через разделы для отказоустойчивости и горизонтальной масштабируемости. Рамки обработки потоков, такие как Kafka Streams, Apache Flink и Spark Streaming, позволяют обрабатывать сложные события с помощью семантики ровно один раз. Например, компания, предоставляющая услуги совместного использования поездок, может передавать местоположения GPS для расчета ценообразования, обнаружения доступности драйверов и обновления ETA-рейдеров - все в режиме реального времени.
Потоковое вещание событий также является основой для сетки данных и событийных микросервисов, где вы хотите отделить производителей данных от потребителей на уровне инфраструктуры данных.
Другие важные шаблоны и шаблоны в сочетании
Сага шаблон
В распределенных транзакциях, особенно в микросервисах, шаблон Saga управляет многоступенчатыми рабочими процессами. Каждый шаг в саге публикует событие или выполняет действие. Если шаг не удается, сага запускает компенсирующие события, чтобы откатить предыдущие шаги. Саги могут быть организованы (центральный координатор сообщает каждой службе, что делать) или поставлены (каждая служба слушает события и решает сама). EDA позволяет хореографировать саги: служба излучает событие, следующая служба делает свою часть, и если она не удается, она излучает событие отказа, которое вызывает откаты. Этот шаблон необходим для поддержания согласованности данных без распределенной блокировки.
Реактивное программирование
Хотя реактивное программирование не является строго архитектурным шаблоном, оно хорошо согласуется с EDA. Такие фреймворки, как RxJS, Reactor и Akka Streams, позволяют разработчикам составлять асинхронную и основанную на событиях логику с использованием наблюдаемых последовательностей. Это особенно полезно для клиентов (например, обновления пользовательского интерфейса в реальном времени) и в серверных потоках, где вам нужно обрабатывать большие объемы событий с обратным давлением.
Сотрудничество в рамках мероприятия
Сотрудничество событий — это шаблон, в котором службы разделяют общую модель событий и общаются исключительно через события. Каждая служба поддерживает свою собственную логику домена и проецирует события в свои собственные хранилища данных. Не существует прямых вызовов API-интерфейса обслуживания. Этот шаблон максимизирует автономность и часто используется в дизайне, ориентированном на домен, с ограниченными контекстами. Основная проблема заключается в версии: когда схема событий изменяется, все потребители должны обновляться или терпеть эволюцию схемы (например, используя Avro или Protobuf с регистрами схем).
Выбираем правильный шаблон
Выбор схемы EDA зависит от ваших конкретных требований.
- Связь и независимость: Если вам нужна высокая разъединенность и много потребителей, Pub/Sub прост. Если вам нужны отдельные модели чтения и записи, объедините CQRS с Event Sourcing.
- Последовательность требует: Для обеспечения сильной согласованности избегайте EDA; используйте распределенные транзакции или базу данных со строгим ACID. Для обеспечения возможной согласованности хорошо работают CQRS и Event Sourcing.
- Пропускная способность и задержка: Потоковое событие (Kafka) обеспечивает лучшую пропускную способность, в то время как Pub / Sub с брокером, таким как RabbitMQ, предлагает меньшую задержку для небольших сообщений.
- Аудиторская способность: Идеально подходит для отраслей с высоким уровнем соответствия.
- Зрелость команды: CQRS и Event Sourcing увеличивают сложность. Убедитесь, что ваша команда понимает возможную согласованность, эволюцию схемы и идемпотентность.
Преимущества Event-Driven Architecture
Помимо непосредственных преимуществ разъединения и масштабируемости, EDA предоставляет ряд операционных и бизнес-преимуществ:
- Масштабируемость: Каждый компонент масштабируется независимо от его собственной нагрузки.В ходе флеш-продажи можно масштабировать сервис заказа и его абонентов, не касаясь услуг выставления счетов или доставки.
- Гибкость: Добавление нового потребителя (например, нового аналитического конвейера) не требует изменений для производителей. Это облегчает разработку системы с течением времени.
- Реагирование в реальном времени: EDA, естественно, поддерживает пользовательский опыт в реальном времени, такой как живые панели инструментов, уведомления и мгновенные обновления.
- Устойчивость: Если потребитель терпит неудачу, события в брокере сохраняются и могут быть воспроизведены. Производители продолжают работать. Эта изоляция предотвращает каскадные сбои.
- Наблюдение: Журналы событий обеспечивают богатый источник данных для мониторинга, оповещения и отладки распределенных следов.
- Интеграция данных: События могут передаваться в озера данных, склады или трубопроводы машинного обучения для аналитики, что делает систему источником истины для всей организации.
Вызовы и лучшие практики
EDA мощная, но не без подводных камней. Общие проблемы включают:
- Всякое согласование: Потребители могут видеть устаревшие данные. Вы должны разрабатывать бизнес-процессы, которые терпят задержки и внедрять идемпотентных обработчиков.
- Сложность: Управление схемами событий, редактирование и множественные потоки событий могут быть сложными. Используйте реестры схем и развивайте схемы с прямой совместимостью.
- Отладка и мониторинг: Распределенные потоки событий проследить сложнее. Инвестируйте в инструменты наблюдения, такие как распределенное отслеживание (Jaeger, OpenTelemetry) и агрегация журналов.
- Дублирование данных: События могут быть дублированы; сделайте ваших потребителей идемпотентными, чтобы обработка события дважды имела тот же эффект, что и обработка его один раз.
- Заказ: Не все потоки событий нуждаются в строгом заказе, но когда они делают (например, переходы состояния одного объекта), раздел по ключу (например, идентификатор объекта) и обеспечивают сохранение брокером порядка в разделе.
Лучшие практики включают в себя: сначала начните с простого — используйте Pub / Sub и добавьте CQRS или Event Sourcing только тогда, когда это оправдано; инвестируйте в хороший реестр схем; обеспечивайте очереди мертвой буквы для неудачных событий; и регулярно моделируйте сбои, чтобы обеспечить работу вашей саги, компенсирующей логику.
Заключение
Модели архитектуры, ориентированные на события - от базового Pub / Sub до более специализированных CQRS, Event Sourcing и потоковой передачи событий - предлагают надежный инструментарий для построения систем, которые масштабируемы, устойчивы и отзывчивы. Благодаря разъединению производителей и потребителей EDA позволяет командам итерировать независимо, изящно обрабатывать непредсказуемые нагрузки и разблокировать возможности в режиме реального времени. Однако она также вводит сложность в согласованность, отладку и управление схемами. Команды, которые инвестируют в понимание компромиссов и внедряют лучшие практики, найдут EDA незаменимым шаблоном для современного проектирования распределенной системы. Поскольку индустрия движется к событиям, управление этими шаблонами больше не является обязательным - это основная компетенция для архитекторов и разработчиков, создающих следующее поколение облачных приложений.