Бессерверная обработка событий

Azure Cosmos DB
Функции Azure
Azure Monitor
Azure Pipelines
Хранилище Azure

Эта эталонная архитектура демонстрирует бессерверную и управляемую событиями архитектуру, которая принимает поток данных, обрабатывает его и записывает результаты в серверную базу данных.

Архитектура

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

Рабочий процесс

  • События поступают в Центры событий Azure.
  • Приложение-функция активируется для обработки события.
  • Событие хранится в базе данных Azure Cosmos DB.
  • Если приложению-функции не удается сохранить событие, событие сохраняется в очереди служба хранилища для последующей обработки.

Компоненты

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

    Примечание.

    Для сценариев Интернета вещей рекомендуется Центр Интернета вещей Azure. Центр Интернета вещей имеет встроенную конечную точку, совместимую с API Центры событий Azure, поэтому вы можете использовать любую службу в этой архитектуре без серьезных изменений во внутренней обработке. Дополнительные сведения см. в статье Подключение устройств Интернета вещей в Azure. Центр Интернета вещей и Центры событий.

  • Приложение-функция. Функции Azure — это независимая от сервера служба вычислений. В нем используется модель на основе событий, в которой вызывается фрагмент кода ( функция) триггером. В этой архитектуре, когда события поступают в Центры событий, они инициируют функцию, которая обрабатывает события и записывает результаты в хранилище.

    Приложения-функции подходят для обработки отдельных записей из Центров событий. Для более сложных сценариев обработки потоков рекомендуется использовать Apache Spark с помощью Azure Databricks или Azure Stream Analytics.

  • Azure Cosmos DB. Azure Cosmos DB — это служба базы данных с несколькими моделями, доступная в бессерверном режиме на основе потребления. В этом сценарии функция обработки событий сохраняет записи JSON с помощью Azure Cosmos DB для NoSQL.

  • Хранилище очередей. Хранилище очередей используется для сообщений с недоставленными буквами. Если при обработке события возникает ошибка, функция сохраняет данные события в очереди недоставленных писем для последующей обработки. Дополнительные сведения см . в разделе "Устойчивость" далее в этой статье.

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

  • Azure Pipelines. Pipelines — это служба непрерывной интеграции (CI) и непрерывной поставки (CD), которая выполняет сборку, тестирование и развертывание приложений.

Рекомендации

Эти рекомендации реализуют основные принципы платформы Azure Well-Architected Framework, которая является набором руководящих принципов, которые можно использовать для улучшения качества рабочей нагрузки. Дополнительные сведения см. в статье Microsoft Azure Well-Architected Framework.

Availability

Представленное здесь развертывание расположено в одном регионе Azure. Для более гибкого подхода к аварийному восстановлению воспользуйтесь функциями геораспределения в различных службах:

  • Центрам событий. Создайте два пространства имен Центров событий: основное (активное) и дополнительное (пассивное). Сообщения автоматически перенаправляются в активное пространство имен, если вы не выполните отработку отказа в дополнительное пространство имен. Дополнительные сведения см. в статье Географическое аварийное восстановление в Центрах событий Azure.
  • Приложение-функция. Разверните второе приложение-функцию, которое ожидает считывания из дополнительного пространства имен Центров событий. Эта функция записывает в вторичную учетную запись хранения для очереди недоставленных писем.
  • Azure Cosmos DB. Azure Cosmos DB поддерживает несколько регионов записи, которые позволяют записывать данные в любой регион, добавленный в учетную запись Azure Cosmos DB. Если вы не включаете многозаписную запись, вы по-прежнему можете выполнить отработку отказа в основном регионе записи. Клиентские пакеты SDK для Azure Cosmos DB и привязки функций Azure автоматически обрабатывают отработку отказа, поэтому вам не нужно обновлять параметры конфигурации приложения.
  • служба хранилища Azure; Используйте хранилище RA-GRS для очереди недоставленных писем. В таком случае создается реплика только для чтения в другом регионе. Если основной регион становится недоступным, вы можете считывать элементы, находящиеся в очереди. Кроме того, можно подготовить другую учетную запись хранения в дополнительном регионе, в которую функция сможет записывать данные после отработки отказа.

Масштабируемость

Event Hubs

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

Триггер Центров событий в приложении-функции масштабируется в соответствии с количеством секций в концентраторе событий. Каждой секции назначается один экземпляр функции за раз. Для увеличения пропускной способности получайте события в пакете, а не по одному за раз.

Azure Cosmos DB

Azure Cosmos DB доступен в двух разных режимах емкости:

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

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

  • Значение пространства ключа велико.
  • Будет существовать равномерное распределение операций чтения и записи на значение ключа, что позволит избежать горячих ключей.
  • Максимальное количество данных, хранящихся для любого значения одного ключа, не превысит максимальный размер физической секции (20 ГБ).
  • Ключ секции для документа не изменится. Обновить ключ секции для существующего документа невозможно.

В сценарии для этой эталонной архитектуры функция хранит только один документ для устройства, отправляющего данные. Функция постоянно обновляет документы с последним состоянием устройства с помощью операции upsert. Идентификатор устройства — это хороший ключ секции для этого сценария, так как записи будут равномерно распределены по ключам, а размер каждой секции будет строго привязан, так как для каждого значения ключа существует один документ. Дополнительные сведения о ключах секций см. в статье Секционирование и масштабирование в Azure Cosmos DB.

Устойчивость

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

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

 [Function(nameof(RawTelemetryFunction))]
 public async Task RunAsync([EventHubTrigger("%EventHubName%", Connection = "EventHubConnection")] EventData[] messages,
     FunctionContext context)
 {
     _telemetryClient.GetMetric("EventHubMessageBatchSize").TrackValue(messages.Length);
     DeviceState? deviceState = null;
     // Create a new CosmosClient
     var cosmosClient = new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTION_STRING"));

     // Get a reference to the database and the container
     var database = cosmosClient.GetDatabase(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_NAME"));
     var container = database.GetContainer(Environment.GetEnvironmentVariable("COSMOSDB_DATABASE_COL"));

     // Create a new QueueClient
     var queueClient = new QueueClient(Environment.GetEnvironmentVariable("DeadLetterStorage"), "deadletterqueue");
     await queueClient.CreateIfNotExistsAsync();

     foreach (var message in messages)
     {
         try
         {
             deviceState = _telemetryProcessor.Deserialize(message.Body.ToArray(), _logger);
             try
             {
                 // Add the device state to Cosmos DB
                 await container.UpsertItemAsync(deviceState, new PartitionKey(deviceState.DeviceId));
             }
             catch (Exception ex)
             {
                  _logger.LogError(ex, "Error saving on database", message.PartitionKey, message.SequenceNumber);
                 var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
                 // Convert the dead letter message to a string
                 var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

                 // Send the message to the queue
                 await queueClient.SendMessageAsync(deadLetterMessageString);
             }

         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "Error deserializing message", message.PartitionKey, message.SequenceNumber);
             var deadLetterMessage = new DeadLetterMessage { Issue = ex.Message, MessageBody = message.Body.ToArray(), DeviceState = deviceState };
             // Convert the dead letter message to a string
             var deadLetterMessageString = JsonConvert.SerializeObject(deadLetterMessage);

             // Send the message to the queue
             await queueClient.SendMessageAsync(deadLetterMessageString);
         }
     }
 }

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

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

    public class DeadLetterMessage
    {
        public string? Issue { get; set; }
        public byte[]? MessageBody { get; set; }
        public DeviceState? DeviceState { get; set; }
    }

Используйте Azure Monitor для мониторинга концентратора событий. Если вы видите входные данные, но нет выходных данных, это означает, что сообщения не обрабатываются. В таком случае перейдите в Log Analytics и поищите исключения или другие ошибки.

DevOps

Используйте инфраструктуру как код (IaC) по возможности. IaC управляет инфраструктурой, приложениями и ресурсами хранилища с декларативным подходом, таким как Azure Resource Manager. Это поможет в автоматизации развертывания с помощью DevOps в качестве решения непрерывной интеграции и непрерывной доставки (CI/CD). Шаблоны должны быть версиями и включены в конвейер выпуска.

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

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

Дополнительные сведения см. в списке проверка DevOps.

Аварийное восстановление

Представленное здесь развертывание расположено в одном регионе Azure. Для более гибкого подхода к аварийному восстановлению воспользуйтесь функциями геораспределения в различных службах:

  • Центры событий. Создайте два пространства имен Центров событий: основное (активное) и дополнительное (пассивное). Сообщения автоматически перенаправляются в активное пространство имен, если вы не выполните отработку отказа в дополнительное пространство имен. Дополнительные сведения см. в статье Географическое аварийное восстановление в Центрах событий Azure.

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

  • Azure Cosmos DB. Azure Cosmos DB поддерживает несколько регионов записи, которые позволяют записывать данные в любой регион, добавленный в учетную запись Azure Cosmos DB. Если вы не включаете многозаписную запись, вы по-прежнему можете выполнить отработку отказа в основном регионе записи. Клиентские пакеты SDK для Azure Cosmos DB и привязки функций Azure автоматически обрабатывают отработку отказа, поэтому вам не нужно обновлять параметры конфигурации приложения.

  • Хранилище Azure. Используйте хранилище RA-GRS для очереди недоставленных писем. В таком случае создается реплика только для чтения в другом регионе. Если основной регион становится недоступным, вы можете считывать элементы, находящиеся в очереди. Кроме того, можно подготовить другую учетную запись хранения в дополнительном регионе, в которую функция сможет записывать данные после отработки отказа.

Оптимизация затрат

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

Используйте калькулятор цен Azure для оценки затрат. Ниже приведены некоторые другие рекомендации по Функции Azure и Azure Cosmos DB.

Функции Azure

Функции Azure поддерживает две модели размещения:

  • План "Потребление". Вычислительная мощность автоматически выделяется при выполнении кода.
  • плана службы приложений. Набор виртуальных машин выделяется для кода. План службы приложений определяет число и размер виртуальных машин.

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

Azure Cosmos DB

С Azure Cosmos DB вы платите за операции, выполняемые с базой данных, и за хранилище, используемое данными.

  • Операции базы данных. Способ оплаты операций с базой данных зависит от типа используемой учетной записи Azure Cosmos DB.
    • В бессерверном режиме вам не нужно подготавливать пропускную способность при создании ресурсов в учетной записи Azure Cosmos DB. В конце периода выставления счетов вы получите счет за количество единиц запросов, потребляемых операциями базы данных.
    • В подготовленном режиме пропускной способности укажите пропускную способность, необходимую в единицах запросов в секунду (ЕЗ/с), и получите почасовую оплату за максимальную подготовленную пропускную способность в течение заданного часа. Примечание. Так как подготовленная модель пропускной способности выделяет ресурсы в контейнер или базу данных, плата будет взиматься за подготовленную пропускную способность, даже если вы не выполняете никаких рабочих нагрузок.
  • Хранилище. Плата взимается за общий объем хранилища (ВБ), потребляемого данными и индексами в течение определенного часа.

В этой эталонной архитектуре функция хранит ровно один документ на устройство, которое отправляет данные. Функция постоянно обновляет документы с последним состоянием устройства, используя операцию upsert, которая является экономически эффективной с точки зрения потребляемого хранилища. Дополнительные сведения см. в модели ценообразования Azure Cosmos DB.

Используйте калькулятор емкости Azure Cosmos DB, чтобы получить быструю оценку затрат на рабочую нагрузку.

Развертывание этого сценария

Логотип GitHub Эталонная реализация этой архитектуры доступна на сайте GitHub.

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