Поделиться через


Стиль архитектуры на основе событий

Архитектура на основе событий состоит из производителей событий , которые создают поток событий, потребителей событий, которые прослушивают эти события, и каналы событий (часто реализуются как брокеры событий или службы приема), которые передают события от производителей к потребителям.

Architecture

Схема, показывающая стиль архитектуры на основе событий.

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

Этот процесс отличается от шаблона конкурирующих потребителей. В шаблоне конкурирующих потребителей потребители извлекают сообщения из очереди. Каждое сообщение обрабатывается только один раз, если нет ошибок. В некоторых системах, таких как Azure IoT, события должны приниматься в больших объемах.

Архитектура на основе событий может использовать модель публикации-подписки или модель потока событий.

  • Публикация-подписка: Инфраструктура обмена сообщениями типа публикация-подписка отслеживает подписки. При публикации события оно отправляет событие каждому подписчику. После получения события он не хранится в устойчивом журнале, поэтому новые подписчики не видят прошлых событий. Мы рекомендуем использовать Azure Event Grid для сценариев публикации и подписки.

  • Потоковая передача событий: События записываются в журнал. События строго упорядочены внутри раздела и являются устойчивыми. Клиенты не подписываются на поток. Вместо этого клиент может читать из любой части потока. Клиент отвечает за перемещение по своей позиции в потоке, что означает, что клиент может присоединяться в любое время и может повторно воспроизводить события. Эта функциональность повторного воспроизведения поддерживает сценарии восстановления, пользователей, которые присоединились позже, и повторную обработку после исправления ошибок. Azure Event Hubs предназначен для потоковой передачи событий высокой пропускной способности.

На стороне потребителя существуют некоторые распространенные варианты:

  • Простая обработка событий: Событие немедленно активирует действие в потребителе. Например, можно использовать Azure Functions с триггером Event Grid или триггером Azure Service Bus, чтобы код был запущен при публикации сообщения.

  • Базовая корреляция событий: Потребитель обрабатывает несколько дискретных бизнес-событий, сопоставляет их идентификатором и сохраняет информацию из предыдущих событий для использования при обработке последующих событий. Библиотеки, такие как NServiceBus и MassTransit , поддерживают этот шаблон.

  • Complex event processing: потребитель использует технологию, например Azure Stream Analytics для анализа ряда событий и определения шаблонов в данных события. Например, можно агрегировать считывания с внедренного устройства с течением времени и создать уведомление, если скользящая средняя превышает определенное пороговое значение.

  • Event stream processing: Использовать платформу потоковой передачи данных, например, Azure IoT Hub, Event Hubs или Event Hubs для Apache Kafka в качестве конвейера для приема событий и передачи их для потоковой передачи процессоров. Обработчики потоков действуют для обработки или преобразования потока. Для разных подсистем приложения может быть несколько процессоров потоков. Этот подход хорошо подходит для рабочих нагрузок Интернета вещей.

Источник событий может быть внешним по отношению к системе, например физическими устройствами в решении Интернет вещей. В этом случае система должна быть способна принимать данные с объемом и скоростью, которые требуются источнику данных.

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

  • Включите все обязательные атрибуты в полезные данные: Используйте этот подход, если требуется, чтобы потребители имели все доступные сведения, не запрашивая внешний источник данных. Большие нагрузки увеличивают затраты на транспорт и потребление пропускной способности и могут привести к проблемам согласованности данных из-за нескольких систем учета, особенно после обновлений. Управление контрактами и управление версиями также могут стать сложными.

  • Включите только ключи в нагрузку: В этом подходе потребители извлекают необходимые атрибуты, такие как первичный ключ, чтобы самостоятельно извлекать оставшиеся данные из источника данных. Этот метод обеспечивает лучшую согласованность данных, так как она имеет единую систему записей. Однако она может иметь хуже производительности, чем первый подход, так как потребители должны часто запрашивать источник данных. У вас меньше проблем с связью, пропускной способностью, управлением контрактами или управлением версиями, так как небольшие события и более простые контракты снижают сложность. Дополнительные сведения см. в разделе "Положите события на диету".

На предыдущей схеме каждый тип потребителя отображается как одно поле. Чтобы избежать того, чтобы потребитель стал единственной точкой отказа в системе, обычно используется несколько экземпляров потребителя. Для обработки объема и частоты событий также может потребоваться несколько экземпляров. Один потребитель может обрабатывать события в нескольких потоках. Эта конфигурация может создавать проблемы, если события должны обрабатываться в строгом порядке или если требуется семантика точной однократной обработки. Дополнительные сведения см. в разделе Минимизация координации.

Существует две основные топологии в архитектуре на основе событий:

  • Топология брокера: Компоненты транслируют события всей системы. Другие компоненты либо реагируют на событие, либо игнорируют его. Эта топология полезна, если поток обработки событий относительно прост. Нет централизованной координации или оркестрации, поэтому эта топология может быть динамической.

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

  • Топология посредника: Эта топология устраняет некоторые недостатки топологии брокера. Существует посредник событий, который управляет и контролирует потоком событий. Посредник событий поддерживает состояние и управляет возможностями обработки ошибок и перезапуска. В отличие от топологии брокера, посредник отправляет команды в назначенные каналы, а не вещание на всю систему. Эти каналы часто являются очередями сообщений. Ожидается, что потребители обработают эти команды.

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

Когда следует использовать эту архитектуру

Эту архитектуру следует использовать при выполнении следующих условий:

  • Несколько подсистем должны обрабатывать одни и те же события.

  • Требуется обработка в режиме реального времени с минимальным временем задержки.

  • Требуется сложная обработка событий, например сопоставление шаблонов или агрегирование с течением времени.

  • Требуются большие объемы и высокая скорость данных, например с Помощью Интернета вещей.

  • Необходимо отделить производителей и потребителей для независимых целей масштабируемости и надежности.

Эта архитектура может не подходить, если:

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

  • Бизнес-транзакции требуют строгой согласованности между службами. Если вы не можете терпеть окна, в которых разные части системы расходятся в текущем состоянии, то "скользкая согласованность," которую вводит событийно-ориентированная архитектура (EDA), может работать против вас.

  • У вашей команды нет работы с распределенными асинхронными системами. Шаблоны отладки, мониторинга и восстановления ошибок, которые требует EDA, существенно отличаются от таковых в синхронных архитектурах, и кривая обучения влияет на сроки доставки.

Преимущества

Эта архитектура обеспечивает следующие преимущества:

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

Сложности

  • Гарантированная доставка

    В некоторых системах, особенно в сценариях Интернета вещей, важно гарантировать доставку событий.

  • Итоговая согласованность

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

    Такое поведение является преднамеренным архитектурным компромиссом. Во многих проектах, управляемых событиями, архитекторы предпочитают использовать доступность и отказоустойчивость секций для определенных рабочих процессов, принимая в конечном итоге согласованность в качестве компромисса, а другие рабочие процессы по-прежнему могут определять более высокую согласованность. Архитекторы должны проектировать системы потребителей и последующие операции чтения, чтобы они терпели устаревшие или частично обновленные данные, когда действует принцип окончательной согласованности. Дополнительные сведения см. в разделе Минимизация координации.

  • Обработка событий последовательно или единожды

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

  • Координация сообщений между службами

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

  • Обработка ошибок

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

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

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

  • Потеря данных

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

  • Наблюдаемость между слабо связанными компонентами

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

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

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

  • Реализация традиционного шаблона ответа на запрос

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

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

  • Поддержка соответствующего количества событий

    Создание чрезмерного количества детализированных событий может насыщать и перегружать систему. Чрезмерный объем событий затрудняет эффективное анализ общего потока событий. Эта проблема усугубляется, когда необходимо откатить изменения. И наоборот, чрезмерно объединенные события также могут создавать проблемы, что приводит к ненужной обработке и ответам со стороны потребителей событий.

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

  • Эволюция схемы событий

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

Другие вопросы

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

  • Многие приложения используют архитектуру на основе событий в качестве основной архитектуры. Этот подход можно объединить с другими архитектурными стилями для создания гибридной архитектуры. Типичные сочетания включают микрослужбы, каналы и фильтры, а также выборку событий. Интегрируйте архитектуру на основе событий, чтобы повысить производительность системы, устраняя узкие места и обеспечивая обратное давление во время больших объемов запросов.

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

Следующий шаг