Проектирование систем, управляемых событиями, для многооблачных развертываний
Эволюция к многооблачным архитектурам, управляемым событиями
Сегодня организации работают с несколькими облачными провайдерами, чтобы избежать блокировки поставщиков, оптимизировать затраты и достичь географического резервирования. По мере созревания этой многооблачной реальности становятся понятными ограничения синхронной связи с запросами: тесная связь между службами, каскадные сбои под нагрузкой и хрупкие интеграции, которые ломаются, когда один провайдер меняет свой API. Архитектура, управляемая событиями (EDA) предлагает убедительную альтернативу, отделяя производителей от потребителей через асинхронные потоки событий. При применении через AWS, Azure, GCP и частные облака, EDA позволяет каждой службе работать независимо, все еще участвуя в согласованных бизнес-процессах.
Основное обещание EDA в многооблачном развертывании — устойчивость: отключение одного провайдера не останавливает обработку событий на других, и события могут быть воспроизведены после устранения сбоев. Этот архитектурный стиль также поддерживает переменную задержку между облаками, поскольку события буферизируются брокерами, а не требуют немедленных ответов. Однако для достижения этих преимуществ требуется тщательный дизайн вокруг совместимости, управления идентификацией и операционной согласованности. Остальная часть этой статьи обеспечивает практическую основу для создания систем, управляемых событиями, которые охватывают несколько облачных сред.
Основные принципы многооблачных систем, управляемых событиями
Разъединение через контракты на события
Каждое событие — это автономное сообщение, описывающее то, что произошло в прошлом. В многооблачной системе эти события должны проходить через облачные границы, то есть контракт между производителем и потребителем должен быть платформо-агностическим. Используйте схемы реестров с CloudEvents в качестве стандартного формата конвертов. Это гарантирует, что служба, работающая на Azure, может потреблять событие, созданное службой на AWS без глубоких знаний по протоколу. Полезная нагрузка события должна содержать только примитивные типы или сериализованные объекты JSON, которые каждая облачная среда выполнения может анализировать изначально.
Асинхронные границы и импотенция
Сетевые разделы между облаками не являются аномалиями; они являются нормальным рабочим состоянием. Каждый потребитель события должен быть идемпотентным: обработка одного и того же события дважды должна давать тот же результат, что и обработка его один раз. Это может быть достигнуто путем включения уникального идентификатора события в полезную нагрузку и поддержания окна дедупликации на стороне потребителя. Например, платежная служба, которая получает событие «ChargeSucceeded», должна проверить, был ли этот идентификатор события уже обработан до применения заряда. Без идемпотентности повторение событий для аварийного восстановления может привести к дублированию заказов, двойным сборам или поврежденному состоянию.
Гарантированная доставка и семантика «по крайней мере один раз»
Большинство многооблачных событийных систем должны быть нацелены на доставку как минимум один раз. Это означает, что брокер признает событие только после того, как оно было устойчиво сохранено, и потребители признают обработку только после того, как событие было безопасно обработано. Хотя теоретически желательно именно один раз доставка, чрезвычайно трудно гарантировать через гетерогенных облачных провайдеров и вводит значительную сложность. По крайней мере один раз в сочетании с идемпотентностью на стороне потребителя является практическим стандартом для производственных систем.
Часовой кальян и временный заказ
События из разных облаков могут нести временные метки, генерируемые машинами с часами, которые не идеально синхронизированы. Не полагайтесь на временные метки событий для заказа в многооблачной системе. Вместо этого используйте логические часы или порядковые номера, назначенные брокером, когда событие впервые сохраняется. Если временный порядок имеет решающее значение, маршрутизируйте связанные события через один раздел на облачно-агностическом брокере, таком как Apache Kafka, где заказ сохраняется на раздел независимо от часов производителя.
Выбор брокеров событий для многооблачных развертываний
Облачные агностические брокеры
Apache Kafka и RabbitMQ — два доминирующих брокера с открытым исходным кодом, которые могут быть развернуты в любом облаке. Kafka превосходит возможности потокового воспроизведения событий с высокой пропускной способностью, долгосрочного удержания событий и повторного воспроизведения. Он идеально подходит для систем, которым необходимо перерабатывать исторические события во время отладки или для обучения модели. RabbitMQ лучше подходит для сложных шаблонов маршрутизации, сценариев ответа на запросы и обмена сообщениями с более низкой задержкой, где пропускная способность умеренна. Оба могут быть развернуты на Kubernetes через несколько облаков с использованием операторов, таких как Strimzi для Kafka или RabbitMQ Cluster Operator.
Управляемые облачные сервисы событий
Каждый крупный облачный провайдер предлагает нативный сервис событий: AWS EventBridge, Google Cloud Pub/Sub и Azure Event Grid. Эти сервисы обеспечивают тесную интеграцию с экосистемой каждого облака, снижая операционные накладные расходы. Однако они вводят связь с проприетарными API и моделями выставления счетов. Чтобы использовать их в многооблачной системе, необходимо создавать разъемы, которые переводят между нативным форматом и общей схемой, такой как CloudEvents. Некоторые команды развертывают единого брокера, такого как Kafka, в центральном облаке и используют реле событий для перехода к управляемым сервисам в других облаках, создавая федерацию, а не однородную сетку.
Брокерская федерация и события Mesh Patterns
Сетка событий соединяет брокеров через облака, не требуя, чтобы весь трафик проходил через один хаб. Каждое облако запускает свой собственный экземпляр брокера, и сетка пересылает события между ними на основе правил маршрутизации. Эта схема снижает затраты на пропускную способность в кросс-облаке и позволяет каждому региону работать независимо. Такие инструменты, как Apache Pulsar, Solace PubSub+ и Confluent Cluster Linking поддерживают родную георепликацию и федерацию. При использовании Kafka вы можете настроить MirrorMaker для репликации тем по кластерам в разных облаках, хотя это вводит возможную согласованность между регионами.
Разработка схем событий и контрактов
CloudEvents как стандартная оболочка
CloudEvents, спецификация, размещенная CNCF, определяет стандартный набор атрибутов для описания событий: , , , , и . Применяя CloudEvents к каждому событию в многооблачной системе, вы получаете единый способ маршрутизации, фильтрации и аудита событий через различных брокеров и облачных границ. Все основные сервисы облачных событий теперь поддерживают CloudEvents изначально, и многие SDK предоставляют сериализаторы для протоколов, включая HTTP, AMQP, MQTT и Kafka.
Реестр схем и их версия
Без общего реестра схем производители и потребители в разных облаках могут незаметно дрейфовать. Производитель может добавить новое поле к событию, которого ожидает потребитель, но поскольку потребитель не знает об изменении, он может отбросить событие. Используйте Apache Avro, Protocol Buffers или JSON Schema с центральным реестром, обеспечивающим обратную совместимость. Каждый тип события должен нести номер версии в расширении CloudEvents или в самой полезной нагрузке. Потребители должны отклонять события с неизвестными версиями, а не молча отбрасывать данные.
Правила совместимости на уровне поля
При разработке схем событий в облаках следуйте этим правилам, чтобы не нарушать правила поведения потребителей:
- Новые поля должны быть необязательными с значениями по умолчанию, которые поддерживают то же поведение, что и предыдущая схема.
- Поле никогда не должно быть удалено, а также обесценивать его, маркируя его как факультативное и исключая его из документации.
- Типы данных не должны меняться. Если поле было целым, оно должно оставаться целым.
- Если требуется структурное изменение, создайте новый тип событий с новым атрибутом типа CloudEvents, а не изменяйте существующий.
Паттерны внедрения для многооблачных систем событий
Источник событий через облака
В многооблачной среде эта схема позволяет различным службам самостоятельно восстанавливать свое состояние, воспроизводя один и тот же поток событий. Центральный магазин событий, обычно поддерживаемый Kafka или прочной базой данных, сохраняет журнал событий. Каждая служба поддерживает свою собственную модель чтения, которую она может реконструировать, воспроизводя события из центрального журнала. Это устраняет необходимость в распределенных транзакциях между облаками, поскольку каждая служба в конечном итоге сходится к правильному состоянию.
Разделение ответственности командного запроса
CQRS отделяет операции записи (команды) от операций чтения (запросы). В многооблачной системе событий команды создаются для потока событий, и одна или несколько служб обрабатывают команды для обновления модели записи. Модели чтения строятся из потока событий и могут быть развернуты в нескольких облаках для доступа к низкозадерживаемым региональным потребителям. Модель записи требует сильных гарантий согласованности, поэтому она обычно развертывается в одной облачной области. Модели чтения могут быть воспроизведены глобально с использованием потока событий в качестве единого источника истины.
Шаблон Saga для распределенных транзакций
Долгосрочные бизнес-процессы, охватывающие несколько облаков, не могут полагаться на транзакции ACID. Вместо этого используйте шаблон саги, где каждый шаг процесса публикует событие, которое запускает следующий шаг. Если шаг не удается, публикуется компенсирующее событие, чтобы откатить предыдущие шаги. Например, сага о бронировании через AWS и Azure может работать следующим образом:
- Сервис на AWS публикует мероприятие «Запрошенная резервация» в Kafka.
- Сервис на Azure обрабатывает мероприятие, проводит инвентаризацию и публикует мероприятие «InventoryHeld».
- Сервис на AWS обрабатывает «InventoryHeld», создает заказ, а также публикует «OrderCreated» событие.
- Если создание заказа не удается, на выпуск проводимого инвентаря направляется событие «Компенсационная инвентаризация».
Сага гарантирует, что каждый участник в каждом облаке выполняет свое действие ровно один раз, с компенсацией действий для поддержания согласованности.
Системы безопасности для многооблачных событий
Шифрование в режиме транзита и в состоянии покоя
Весь трафик событий между облаками должен быть зашифрован с помощью TLS 1.2 или выше. Ссылки репликации брокера-брокера должны использовать взаимную аутентификацию TLS. События, сохраняющиеся в журнале брокера или в магазинах ниже по течению, должны быть зашифрованы в покое с использованием ключей, управляемых облачным провайдером, или ключей, управляемых клиентом (CMK). При использовании облачного агностического брокера, развернутого на Kubernetes, используйте сервисную сеть, такую как Istio или Linkerd, чтобы обеспечить соблюдение mTLS между всеми стручками производителя событий и потребителя через облака.
Аутентификация и авторизация между облаками
Каждый облачный провайдер имеет свою собственную систему идентификации: IAM на AWS, Azure Active Directory и Cloud IAM на GCP. Для аутентификации производителя в одном облаке брокеру в другом используйте либо недолговечные токены, генерируемые личностью производителя и подтвержденные брокером, либо используйте общий сертификат клиента. Избегайте долгоживущих статических учетных данных, таких как ключи API, встроенные в код приложения. Храните секреты в кросс-облачном хранилище, таком как хранилище HashiCorp или диспетчер секретов AWS с репликацией в другие облака.
Проверка регистрации и отслеживаемости событий
Каждое событие, пересекающее границу облака, должно нести идентификатор трассировки, который распространяется через всю обработку в нисходящем потоке. Используйте расширение CloudEvents или аналогичный механизм распределенного отслеживания. Централизованные журналы аудита должны захватывать идентификатор события, облако источника, целевое облако, временную метку и результат обработки. Эти журналы необходимы для соответствия, отладки и выставления счетов в облаках.
Мониторинг и наблюдение через облачные границы
Централизованные метрики событий
Совокупные показатели от брокеров событий во всех облаках в единую систему мониторинга. Ключевые показатели для отслеживания включают:
- Уровень производства на одного производителя и на тип
- Отставание потребителей в группе потребителей и в разделе
- Задержка межоблачных событий от производства к потреблению
- Частота неудач и причины неудачи
- Использование диска брокера и пропускная способность сети
Используйте Prometheus с Таносом или Графана Мимиром для запроса метрик в нескольких облачных развертываниях без потери контекста.
Распределенная трассировка событий в кросс-облаке
Когда событие происходит в одном облаке и запускает цепочку обработки в других облаках, трудно отлаживать проблемы производительности без распределенного отслеживания. Развернуть сборщики OpenTelemetry в каждом облаке, которые пересылают данные трассировки в центральный бэкэнд, такой как Jaeger или Grafana Tempo. Убедитесь, что каждый обработчик событий распространяет контекст трассировки, даже когда обработчик является бессерверной функцией, которая масштабируется до нуля между вызовами. Многие управляемые службы событий теперь поддерживают из коробки приборы OpenTelemetry.
Проверка здоровья на конец мероприятия
Запланируйте синтетические события, которые проходят через весь конвейер событий от производства в одном облаке до потребления в другом. Измерьте время в оба конца и пометьте любые аномалии. Если синтетические события не попадают в ожидаемое окно, вызовите оповещение. Этот вид проверки здоровья улавливает бесшумные сбои, такие как неправильно настроенное правило брандмауэра, полное состояние диска брокера или несовместимость схемы, которая не будет видна только из метрик.
Реальные случаи использования
Многооблачная оркестровка ордеров
Глобальная компания электронной коммерции обрабатывает заказы, которые включают управление запасами на AWS, обработку платежей на Azure и логистику доставки на GCP. Каждый шаг в жизненном цикле заказа - это событие, которое проходит через общий кластер Kafka, развернутый через три облака. Заказ, размещенный в регионе США Запад, производит событие «OrderPlaced», которое потребляется службами запасов на AWS, которые затем производят события «InventoryAllocated». Платежная служба на Azure потребляет событие распределения и обрабатывает заряд, производя «PaymentSettled». Служба доставки на GCP, наконец, потребляет урегулирование и намечает доставку. Если какой-либо шаг не удается, событие компенсации производится, чтобы откатить предыдущие шаги в саге.
Многооблачный IoT Data Ingestion
Промышленная IoT-платформа собирает данные датчиков с заводов по всему миру. Каждая фабрика отправляет данные в ближайший облачный регион, который может быть AWS в Северной Америке, Azure в Европе или GCP в Азии. Каждый региональный брокер поглощает необработанные данные датчиков и публикует их в локальном потоке событий. Глобальная сетка событий копирует ключевые события в центральном кластере Kafka, где ученые данных запускают модели обнаружения аномалий. Обработанные результаты затем публикуются обратно через сетку региональным брокерам, которые отправляют команды на заводские исполнительные механизмы. Весь трубопровод должен обрабатывать переменную задержку между регионами, обеспечивая при этом доставку командных событий для каждого датчика.
Обычные подводные камни и как их избежать
Предполагая однородную задержку между облаками
Задержка сети в кросс-облаке может варьироваться от 10 мс до более 500 мс в зависимости от географического расстояния, интернет-заторов и соглашений о пиринге с облачным провайдером. Проектируйте тайм-ауты событий, интервалы повторных попыток и тайм-ауты потребителей на основе измерений, а не предположений. Используйте матрицу сетевого ожидания из выбранных вами облачных регионов и регулярно обновляйте ее, поскольку поставщики добавляют новые пиринговые соединения.
Использование георепликации брокера для обеспечения сильной согласованности
Большинство механизмов репликации брокеров в облаках в конечном итоге согласуются по дизайну. Если производитель в одном облаке пишет событие, а затем сразу читает от потребителя в другом облаке, потребитель может не видеть событие в течение секунд или минут. Не проектируйте рабочие процессы, которые требуют сильной согласованности чтения после записи через границы облака. Вместо этого направляйте потребителя производителя к тому же экземпляру брокера для этой конкретной операции или принимайте возможную согласованность в качестве ограничения дизайна.
Пренебрежение кросс-облачным интерфейсом
Передача данных между облаками может быть дорогостоящей. Каждое событие, которое пересекает границу облака, несет расходы на выход от поставщика источника и расходы на вход от поставщика назначения. Оцените ежемесячный объем события и средний размер полезной нагрузки для расчета прогнозируемых затрат. Рассмотрим такие стратегии, как сжатие полезных нагрузок события, снижение частоты событий или запуск выделенной прямой схемы подключения между основными развертываниями облаков для снижения скорости выхода в открытый Интернет.
Заключение
Разработка событийно-ориентированных систем для развертывания в нескольких облаках требует перехода от инфраструктурно-ориентированного мышления к дизайну, ориентированному на контракт. Стандартизированные схемы, идемпотентные потребители и брокерская федерация образуют основу систем, которые могут пережить перебои с поставщиками, сетевые разделы и непредсказуемые модели нагрузки. Модели, описанные здесь — поиск событий, CQRS и sagas — обеспечивают проверенные подходы для поддержания согласованности данных и устойчивости в гетерогенных средах.
Начните с принятия CloudEvents в качестве универсального конверта, разверните облачно-агностический брокер, такой как Apache Kafka или Pulsar, по крайней мере, в двух облаках, и создайте синтетические проверки здоровья, которые проверяют сквозной конвейер. Со временем расширяйте систему с управляемыми сервисами событий, где они обеспечивают явную операционную выгоду, но всегда сохраняйте контракт на мероприятие независимым от любого отдельного поставщика. Результатом является система, которая не просто многооблачная, но действительно облачно-агностическая — одна, которая может развиваться по мере развития вашей инфраструктурной стратегии.