Шаблон современного веб-приложения для .NET

Служба приложений Azure
Azure Front Door
Кэш Azure для Redis
.NET

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

Почему используйте шаблон современного веб-приложения?

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

Реализация шаблона современного веб-приложения

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

  • Руководство по архитектуре. Узнайте, как модульизировать компоненты веб-приложения и выбрать соответствующие решения платформы как услуга (PaaS).
  • Руководство по коду. Реализация четырех шаблонов проектирования для оптимизации разделенных компонентов: Strangler Fig, выравнивания нагрузки на основе очередей, конкурирующих потребителей и шаблонов мониторинга конечных точек работоспособности.
  • Руководство по настройке: настройка проверки подлинности, авторизации, автомасштабирования и контейнеризации для компонентов, разделенных.

Совет

Логотип GitHub Существует эталонная реализация (пример приложения) шаблона современного веб-приложения. Он представляет конечное состояние реализации современного веб-приложения. Это рабочее веб-приложение, которое содержит все обновления кода, архитектуры и конфигурации, рассмотренные в этой статье. Развертывание и использование эталонной реализации для реализации шаблона современного веб-приложения.

Руководство по архитектуре

Шаблон современного веб-приложения основан на шаблоне Reliable Web App. Для реализации требуется несколько дополнительных архитектурных компонентов. Вам нужна очередь сообщений, платформа контейнеров, хранилище данных службы и реестр контейнеров (см. рис. 1).

Схема, показывающая базовую архитектуру шаблона современного веб-приложения.Рис. 1. Основные архитектурные элементы шаблона современного веб-приложения.

Для более высокого уровня обслуживания (SLO) можно добавить второй регион в архитектуру веб-приложения. Второй регион требует настройки подсистемы балансировки нагрузки для маршрутизации трафика во второй регион для поддержки конфигурации "активный— активный" или "активный- пассивный". Используйте топологию сети концентратора и периферийной сети для централизованной и общей работы ресурсов, таких как брандмауэр сети. Доступ к репозиторию контейнеров через виртуальную сеть концентратора. Если у вас есть виртуальные машины, добавьте узел бастиона в виртуальную сеть концентратора для безопасного управления ими (см. рис. 2).

Схема, показывающая архитектуру шаблона современного веб-приложения со второй областью и топологией сети с концентраторами и периферийными сетями.Рис. 2. Архитектура шаблона современного веб-приложения со второй областью и топологией сети с концентратором и периферийной сетью.

Архитектура decouple

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

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

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

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

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

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

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

  • Реализуйте отдельные конвейеры развертывания для каждой отдельной службы. Отдельные конвейеры развертывания позволяют обновлять каждую службу по своему темпу. Если разные команды или организации в вашей компании имеют разные службы, то отдельные конвейеры развертывания предоставляют каждому команду контроль над собственными развертываниями. Используйте средства CI/CD, такие как Jenkins, GitHub Actions или Azure Pipelines, чтобы настроить эти конвейеры.

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

Выберите нужные службы Azure

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

  • Выберите очередь сообщений. Очередь сообщений — это важная часть архитектуры, ориентированной на обслуживание. Он отделяет отправителей сообщений и получателей для включения асинхронного обмена сообщениями. Используйте рекомендации по выбору службы обмена сообщениями Azure, чтобы выбрать систему обмена сообщениями Azure, которая поддерживает ваши потребности в проектировании. В Azure есть три службы обмена сообщениями: Сетка событий Azure, Центры событий Azure и Служебная шина Azure. Начните с Служебная шина Azure в качестве варианта по умолчанию и используйте другие два варианта, если Служебная шина Azure не соответствует вашим потребностям.

    Service Вариант использования
    Служебная шина Azure Выберите Служебная шина Azure для надежной, упорядоченной и, возможно, транзакционной доставки сообщений с высоким уровнем ценности в корпоративных приложениях.
    Сетку событий Azure Выберите Сетка событий Azure, когда необходимо эффективно обрабатывать большое количество дискретных событий. Сетка событий Azure можно масштабировать для приложений, управляемых событиями, где требуется перенаправить множество небольших независимых событий (например, изменений состояния ресурсов) подписчикам в модели с низкой задержкой, модель публикации и подписки.
    Центры событий Azure Выберите Центры событий Azure для массового приема данных с высокой пропускной способностью, например телеметрии, журналов или аналитики в режиме реального времени. Центры событий Azure оптимизировано для сценариев потоковой передачи, в которых массовые данные должны обрабатываться и обрабатываться непрерывно.
  • Реализуйте службу контейнеров. Для частей приложения, которые требуется контейнеризировать, требуется платформа приложений, поддерживающая контейнеры. Используйте руководство по выбору службы контейнеров Azure для принятия решения. В Azure есть три основных службы контейнеров: приложения контейнеров Azure, Служба Azure Kubernetes и Служба приложений. Начните с приложений контейнеров Azure в качестве варианта по умолчанию и используйте другие два варианта, если приложения контейнеров Azure не соответствуют вашим потребностям.

    Service Вариант использования
    Приложения контейнеров Azure (ACA) Выберите ACA, если вам нужна бессерверная платформа, которая автоматически масштабирует контейнеры и управляет контейнерами в приложениях на основе событий.
    Служба Azure Kubernetes (AKS) Выберите AKS, если вам нужен подробный контроль над конфигурациями Kubernetes и расширенными функциями масштабирования, сети и безопасности.
    веб-приложения для контейнера Выберите веб-приложение для контейнеров в службе приложение Azure для простого интерфейса PaaS.
  • Реализуйте репозиторий контейнеров. При использовании любой вычислительной службы на основе контейнеров необходимо иметь репозиторий для хранения образов контейнеров. Вы можете использовать общедоступный реестр контейнеров, например Docker Hub или управляемый реестр, например Реестр контейнеров Azure. Чтобы принять решение, используйте общие сведения о реестрах контейнеров в Azure.

Руководство по коду

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

Схема, показывающая роль шаблонов проектирования в архитектуре шаблона современного веб-приложения.Рис. 3. Роль шаблонов проектирования.

  1. Шаблон Strangler Fig: шаблон Strangler Fig добавочно переносит функциональные возможности из монолитного приложения в службу, разделенную. Реализуйте этот шаблон в основном веб-приложении для постепенной миграции функций в независимые службы путем направления трафика на основе конечных точек.

  2. Шаблон выравнивания нагрузки на основе очередей: шаблон выравнивания нагрузки на основе очередей управляет потоком сообщений между производителем и потребителем с помощью очереди в качестве буфера. Реализуйте этот шаблон в части производителя отдельной службы для асинхронного управления потоком сообщений с помощью очереди.

  3. Шаблон конкурирующих потребителей: шаблон конкурирующих потребителей позволяет нескольким экземплярам развязанной службы независимо считывать из одной очереди сообщений и конкурировать с обработкой сообщений. Реализуйте этот шаблон в развязанной службе для распределения задач между несколькими экземплярами.

  4. Шаблон мониторинга конечных точек работоспособности: шаблон мониторинга конечных точек работоспособности предоставляет конечные точки для мониторинга состояния и работоспособности различных частей веб-приложения. (4a) Реализуйте этот шаблон в основном веб-приложении. (4b) Кроме того, реализуйте его в отдельной службе для отслеживания работоспособности конечных точек.

  5. Шаблон повторных попыток: шаблон повторных попыток обрабатывает временные сбои путем повторения операций, которые могут периодически завершаться ошибкой. (5a) Реализуйте этот шаблон во всех исходящих вызовах других служб Azure в основном веб-приложении, таких как вызовы очереди сообщений и частные конечные точки. (5b) Кроме того, реализуйте этот шаблон в отдельной службе для обработки временных сбоев в вызовах частных конечных точек.

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

Шаблон разработки Расположение реализации Надежность (RE) Безопасность (SE) Оптимизация затрат (CO) Операционное превосходство (OE) Эффективность производительности (PE) Поддержка принципов WAF
Шаблон strangler Fig Основное веб-приложение RE:08
CO:07
CO:08
OE:06
OE:11
Шаблон выравнивания нагрузки на основе очередей Производитель развязанной службы RE:06
RE:07
CO:12
PE:05
Шаблон конкурирующих потребителей Отсоединяемая служба RE:05
RE:07
CO:05
CO:07
PE:05
PE:07
Шаблон мониторинга конечных точек работоспособности Основное веб-приложение и несоединяемая служба RE:07
RE:10
OE:07
PE:05
Шаблон повторных попыток Основное веб-приложение и несоединяемая служба RE:07

Реализация шаблона Strangler Fig

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

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

  • Управление развертыванием компонентов. Используйте библиотеки управления функциями .NET для реализации флагов компонентов и поэтапного развертывания для постепенного развертывания разложенных служб. Существующая монолитная маршрутизация приложений должна контролировать количество запросов, получаемых несвязанными службами. Начните с небольшого процента запросов и увеличение использования с течением времени, так как вы получаете уверенность в его стабильности и производительности. Например, эталонная реализация извлекает функции отрисовки билетов в автономную службу, которая может постепенно появиться для обработки большей части запросов на отрисовку билетов. Так как новая служба подтверждает свою надежность и производительность, она в конечном итоге может взять на себя всю функциональность отрисовки билетов из монолита, завершив переход.

  • Используйте службу фасада (при необходимости). Служба фасада полезна, если один запрос должен взаимодействовать с несколькими службами или когда требуется скрыть сложность базовой системы от клиента. Однако если у службы, разделенной, нет общедоступных API- интерфейсов, служба фасада может не потребоваться. В базе кода монолитного веб-приложения реализуйте службу фасада для маршрутизации запросов на соответствующую серверную часть (монолит или микрослужбу). В новой отдельной службе убедитесь, что новая служба может обрабатывать запросы независимо при доступе через фасад.

Реализация шаблона выравнивания нагрузки на основе очередей

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

  • Используйте очередь сообщений без блокировки. Убедитесь, что процесс, отправляющий сообщения в очередь, не блокирует другие процессы, ожидая отсоединяемой службы для обработки сообщений в очереди. Если для процесса требуется результат операции отсоединяемой службы, можно использовать альтернативный способ обработки ситуации, ожидая завершения операции в очереди. Например, эталонная реализация использует Служебная шина Azure и await ключевое слово для messageSender.PublishAsync() асинхронной публикации сообщений в очередь без блокировки потока, выполняющего этот код:

    // Asynchronously publish a message without blocking the calling thread
    await messageSender.PublishAsync(new TicketRenderRequestMessage(Guid.NewGuid(), ticket, null, DateTime.Now), CancellationToken.None);
    

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

  • Реализация повторных попыток и удаления сообщений. Реализуйте механизм для повторной обработки очередных сообщений, которые невозможно обработать успешно. Если сбои сохраняются, эти сообщения следует удалить из очереди. Например, Служебная шина Azure имеет встроенные функции повторных попыток и очереди недоставленных писем.

  • Настройте идемпотентную обработку сообщений. Логика, которая обрабатывает сообщения из очереди, должна быть идемпотентной для обработки случаев, когда сообщение может обрабатываться более одного раза. Например, эталонная реализация используется ServiceBusClient.CreateProcessor и AutoCompleteMessages = true ReceiveMode = ServiceBusReceiveMode.PeekLock гарантирует, что сообщения обрабатываются только один раз и могут быть повторно обработаны при сбое (см. следующий код).

    // Create a processor for idempotent message processing
    var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions
    {
        // Allow the messages to be auto-completed
        // if processing finishes without failure.
        AutoCompleteMessages = true,
    
        // PeekLock mode provides reliability in that unsettled messages
        // will be redelivered on failure.
        ReceiveMode = ServiceBusReceiveMode.PeekLock,
    
        // Containerized processors can scale at the container level
        // and need not scale via the processor options.
        MaxConcurrentCalls = 1,
        PrefetchCount = 0
    });
    
  • Управление изменениями в интерфейсе. Асинхронная обработка может привести к тому, что задачи не выполняются немедленно. Пользователи должны знать, когда их задача по-прежнему обрабатывается, чтобы задать правильные ожидания и избежать путаницы. Используйте визуальные подсказки или сообщения, чтобы указать, что выполняется задача. Предоставьте пользователям возможность получать уведомления при выполнении задачи, например сообщение электронной почты или push-уведомление.

Реализация шаблона конкурирующих потребителей

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

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

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

  • Обработка параллельных сообщений. При получении сообщений из очереди убедитесь, что система предназначена для одновременной обработки нескольких сообщений. Задайте максимальное число одновременных вызовов 1, чтобы отдельный потребитель обрабатывал каждое сообщение.

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

  • Используйте режимы надежной обработки сообщений. Используйте режим надежной обработки, например PeekLock (или его эквивалент), который автоматически повторяет сообщения, которые завершаются сбоем. Этот режим повышает надежность по сравнению с методами удаления. Если не удается обработать сообщение, другой должен иметь возможность обрабатывать его без ошибок, даже если сообщение обрабатывается несколько раз.

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

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

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

  • Используйте очередь ответа на сообщение. Если системе требуются уведомления после обработки сообщений, настройте выделенную очередь ответа или ответа. Эта настройка разделяет операционные сообщения от процессов уведомлений.

  • Используйте службы без отслеживания состояния. Рассмотрите возможность использования служб без отслеживания состояния для обработки запросов из очереди. Это позволяет легко масштабировать и эффективно использовать ресурсы.

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

Например, эталонная реализация использует шаблон конкурирующих потребителей в службе без отслеживания состояния, работающей в приложении контейнера Azure, для обработки запросов на отрисовку билетов из очереди Служебная шина Azure. Он настраивает обработчик очередей с помощью:

  • AutoCompleteMessages: автоматически завершает сообщения при обработке без сбоя.
  • ReceiveMode: использует режим PeekLock и повторное создание сообщений, если они не урегулированы.
  • MaxConcurrentCalls: установите значение 1 для обработки одного сообщения за раз.
  • PrefetchCount: установите значение 0, чтобы избежать предварительной выборки сообщений.

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

// Create a processor for the given queue that will process
// incoming messages.
var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions
{
    // Allow the messages to be auto-completed
    // if processing finishes without failure.
    AutoCompleteMessages = true,
    // PeekLock mode provides reliability in that unsettled messages
    // are redelivered on failure.
    ReceiveMode = ServiceBusReceiveMode.PeekLock,
    // Containerized processors can scale at the container level
    // and need not scale via the processor options.
    MaxConcurrentCalls = 1,
    PrefetchCount = 0
});

// Called for each message received by the processor.
processor.ProcessMessageAsync += async args =>
{
    logger.LogInformation("Processing message {MessageId} from {ServiceBusNamespace}/{Path}", args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
    // Unhandled exceptions in the handler will be caught by
    // the processor and result in abandoning and dead-lettering the message.
    try
    {
        var message = args.Message.Body.ToObjectFromJson<T>();
        await messageHandler(message, args.CancellationToken);
        logger.LogInformation("Successfully processed message {MessageId} from {ServiceBusNamespace}/{Path}",args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
    }
    catch (JsonException)
    {
        logger.LogError("Invalid message body; could not be deserialized to {Type}", typeof(T));
        await args.DeadLetterMessageAsync(args.Message, $"Invalid message body; could not be deserialized to {typeof(T)}",cancellationToken: args.CancellationToken);
    }
};

Реализация шаблона мониторинга конечной точки работоспособности

Реализуйте шаблон мониторинга конечных точек работоспособности в основном коде приложения и отсоедините код службы для отслеживания работоспособности конечных точек приложения. Оркестраторы, такие как Служба Azure Kubernetes или приложения контейнеров Azure, могут опрашивать эти конечные точки, чтобы проверить работоспособность службы и перезапустить неработоспособные экземпляры. ASP.NET приложения Core могут добавлять выделенное ПО промежуточного слоя проверки работоспособности для эффективного обслуживания данных работоспособности конечных точек и зависимостей ключей. Чтобы реализовать шаблон мониторинга конечных точек работоспособности, выполните следующие рекомендации.

  • Реализуйте проверки работоспособности. Используйте по промежуточному слоям проверки работоспособности ASP.NET Core для предоставления конечных точек проверки работоспособности.

  • Проверка зависимостей. Убедитесь, что проверка работоспособности проверяет доступность зависимостей ключей, таких как база данных, хранилище и система обмена сообщениями. Пакет, отличный от Майкрософт, AspNetCore.Diagnostics.HealthChecks, может реализовать проверки зависимостей проверки работоспособности для многих распространенных зависимостей приложений.

    Например, эталонная реализация использует ПО промежуточного слоя проверки работоспособности ядра ASP.NET для предоставления конечных точек проверки работоспособности с помощью AddHealthChecks() метода в объекте builder.Services . Код проверяет доступность зависимостей ключей, Хранилище BLOB-объектов Azure и Служебная шина Azure очереди с помощью AddAzureBlobStorage() методов и AddAzureServiceBusQueue() методов, входящих AspNetCore.Diagnostics.HealthChecks в пакет. Приложения контейнеров Azure позволяют настраивать пробы работоспособности, отслеживаемые для оценки работоспособности приложений или необходимости повторной переработки.

    // Add health checks, including health checks for Azure services
    // that are used by this service.
    // The Blob Storage and Service Bus health checks are provided by
    // AspNetCore.Diagnostics.HealthChecks
    // (a popular open source project) rather than by Microsoft. 
    // https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks
    builder.Services.AddHealthChecks()
    .AddAzureBlobStorage(options =>
    {
        // AddAzureBlobStorage will use the BlobServiceClient registered in DI
        // We just need to specify the container name
        options.ContainerName = builder.Configuration.GetRequiredConfigurationValue("App:StorageAccount:Container");
    })
    .AddAzureServiceBusQueue(
        builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:Host"),
        builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:RenderRequestQueueName"),
        azureCredentials);
    
    // Further app configuration omitted for brevity
    app.MapHealthChecks("/health");
    
  • Настройте ресурсы Azure. Настройте ресурсы Azure для использования URL-адресов проверки работоспособности приложения для подтверждения активности и готовности. Например, эталонная реализация использует Bicep для настройки URL-адресов проверки работоспособности для подтверждения активности и готовности ресурса Azure. Проба активности для попадания в /health конечную точку каждые 10 секунд после начальной задержки в 2 секунды.

    probes: [
      {
        type: 'liveness'
        httpGet: {
          path: '/health'
          port: 8080
        }
        initialDelaySeconds: 2
        periodSeconds: 10
      }
    ]
    

Реализация шаблона повторных попыток

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

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

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

  • Используйте функцию повторных попыток пакета SDK. Для служб с специализированными пакетами SDK, такими как Служебная шина Azure или Хранилище BLOB-объектов Azure, используйте встроенные механизмы повторных попыток. Встроенные механизмы повторных попыток оптимизированы для типичных вариантов использования службы и могут эффективно обрабатывать повторные попытки с меньшей конфигурацией, необходимой для вашей части. Например, эталонная реализация использует встроенные функции повторных попыток пакета SDK Служебная шина Azure (ServiceBusClientиServiceBusRetryOptions). Объекты ServiceBusRetryOptions извлекает параметры из MessageBusOptions настройки параметров повторных попыток, таких как MaxRetries, Delay, MaxDelay и TryTimeout.

    // ServiceBusClient is thread-safe and can be reused for the lifetime
    // of the application.
    services.AddSingleton(sp =>
    {
        var options = sp.GetRequiredService<IOptions<MessageBusOptions>>().Value;
        var clientOptions = new ServiceBusClientOptions
        {
            RetryOptions = new ServiceBusRetryOptions
            {
                Mode = ServiceBusRetryMode.Exponential,
                MaxRetries = options.MaxRetries,
                Delay = TimeSpan.FromSeconds(options.BaseDelaySecondsBetweenRetries),
                MaxDelay = TimeSpan.FromSeconds(options.MaxDelaySeconds),
                TryTimeout = TimeSpan.FromSeconds(options.TryTimeoutSeconds)
            }
        };
        return new ServiceBusClient(options.Host, azureCredential ?? new DefaultAzureCredential(), clientOptions);
    });
    
  • Внедрение стандартных библиотек устойчивости для HTTP-клиентов. Для связи HTTP интегрируйте стандартную библиотеку устойчивости, например Polly или Microsoft.Extensions.Http.Resilience. Эти библиотеки предлагают комплексные механизмы повторных попыток, которые являются важными для управления взаимодействием с внешними веб-службами.

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

Реализация распределенной трассировки

Поскольку приложения становятся более ориентированными на обслуживание и их компоненты отделены, мониторинг потока выполнения между службами имеет решающее значение. Шаблон современного веб-приложения использует приложение Azure Insights и Azure Monitor для видимости работоспособности приложений и производительности с помощью API OpenTelemetry, которые поддерживают распределенную трассировку.

Распределенная трассировка отслеживает запрос пользователя по мере прохождения нескольких служб. При получении запроса он помечается идентификатором трассировки, который передается другим компонентам через заголовки HTTP и служебная шина свойства во время вызова зависимостей. Затем трассировки и журналы включают идентификатор трассировки и идентификатор действия (или идентификатор диапазона), соответствующий конкретному компоненту и его родительскому действию. Средства мониторинга, такие как Application Insights, используют это для отображения дерева действий и журналов в разных службах, важных для мониторинга распределенных приложений.

  • Установите библиотеки OpenTelemetry. Используйте библиотеки инструментирования для включения трассировки и метрик из распространенных компонентов. Добавьте настраиваемое инструментирование с System.Diagnostics.ActivitySource помощью и System.Diagnostics.Activity при необходимости. Используйте библиотеки экспортеров для прослушивания диагностика OpenTelemetry и записи их в постоянных хранилищах. Используйте существующие экспортеры или создайте собственные System.Diagnostics.ActivityListenerс помощью .

  • Настройка OpenTelemetry. Используйте распределение OpenTelemetry (Azure.Monitor.OpenTelemetry.AspNetCore) в Azure Monitor. Убедитесь, что он экспортирует диагностика в Application Insights и включает встроенную инструментирование для общих метрик, трассировок, журналов и исключений из среды выполнения .NET и ASP.NET Core. Включите дополнительные пакеты инструментирования OpenTelemetry для клиентов SQL, Redis и Azure SDK.

  • Мониторинг и анализ. После настройки убедитесь, что журналы, трассировки, метрики и исключения записываются и отправляются в Application Insights. Убедитесь, что включены идентификаторы трассировки, активности и родительского действия, что позволяет Application Insights предоставлять сквозную видимость трассировки через границы HTTP и служебная шина. Используйте эту настройку для эффективного мониторинга и анализа действий приложения в разных службах.

В примере современного веб-приложения используется распределение OpenTelemetryAzure.Monitor.OpenTelemetry.AspNetCore () в Azure Monitor. Дополнительные пакеты инструментирования используются для клиентов SQL, Redis и Azure SDK. OpenTelemetry настроен в примере службы отрисовки билетов в современном веб-приложении следующим образом:

builder.Logging.AddOpenTelemetry(o => 
{ 
    o.IncludeFormattedMessage = true; 
    o.IncludeScopes = true; 
}); 

builder.Services.AddOpenTelemetry() 
    .UseAzureMonitor(o => o.ConnectionString = appInsightsConnectionString) 
    .WithMetrics(metrics => 
    { 
        metrics.AddAspNetCoreInstrumentation() 
                .AddHttpClientInstrumentation() 
                .AddRuntimeInstrumentation(); 
    }) 
    .WithTracing(tracing => 
    { 
        tracing.AddAspNetCoreInstrumentation() 
                .AddHttpClientInstrumentation() 
                .AddSource("Azure.*"); 
    }); 

Метод builder.Logging.AddOpenTelemetry направляет все журналы через OpenTelemetry, обеспечивая согласованность трассировки и ведения журнала в приложении. Зарегистрируя службы OpenTelemetry, builder.Services.AddOpenTelemetryприложение настраивается для сбора и экспорта диагностика, которые затем отправляются в приложение Azure Insights через UseAzureMonitor. Кроме того, инструментирование клиентов для таких компонентов, как Служебная шина Azure и HTTP-клиенты, настраивается с помощью WithMetrics WithTracingи включает автоматические метрики и коллекцию трассировок, не требуя изменений в существующем использовании клиента, только обновление конфигурации.

Руководство по настройке

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

Настройка Надежность (RE) Безопасность (SE) Оптимизация затрат (CO) Операционное превосходство (OE) Эффективность производительности (PE) Поддержка принципов WAF
Настройка проверки подлинности и авторизации SE:05
OE:10
Реализация независимого автомасштабирования RE:06
CO:12
PE:05
Развертывание службы containerize CO:13
PE:09
PE:03

Настройка проверки подлинности и авторизации

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

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

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

  • Внедрение инфраструктуры в качестве кода (IaC). Используйте средства Azure Bicep или аналогичные средства IaC для определения облачных ресурсов и управления ими. IaC обеспечивает согласованное применение конфигураций безопасности в развертываниях и позволяет управлять версиями настройки инфраструктуры.

Чтобы настроить проверку подлинности и авторизацию для пользователей (удостоверений пользователей), выполните следующие рекомендации.

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

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

Эталонная реализация использует IaC для назначения управляемых удостоверений добавленным службам и определенным ролям для каждого удостоверения. Он определяет роли и разрешения для развертывания (containerRegistryPushRoleId), владельца приложения (containerRegistryPushRoleId) и приложения приложений контейнеров Azure () (containerRegistryPullRoleIdсм. следующий код).

roleAssignments: \[
    {
    principalId: deploymentSettings.principalId
    principalType: deploymentSettings.principalType
    roleDefinitionIdOrName: containerRegistryPushRoleId
    }
    {
    principalId: ownerManagedIdentity.outputs.principal_id
    principalType: 'ServicePrincipal'
    roleDefinitionIdOrName: containerRegistryPushRoleId
    }
    {
    principalId: appManagedIdentity.outputs.principal_id
    principalType: 'ServicePrincipal'
    roleDefinitionIdOrName: containerRegistryPullRoleId
    }
\]

Эталонная реализация назначает управляемое удостоверение в качестве нового удостоверения приложения контейнера Azure при развертывании (см. следующий код).

module renderingServiceContainerApp 'br/public:avm/res/app/container-app:0.1.0' = {
  name: 'application-rendering-service-container-app'
  scope: resourceGroup()
  params: {
    // Other parameters omitted for brevity
    managedIdentities: {
      userAssignedResourceIds: [
        managedIdentity.id
      ]
    }
  }
}

Настройка независимого автомасштабирования

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

  • Используйте службы без отслеживания состояния. Убедитесь, что службы без отслеживания состояния. Если приложение .NET содержит состояние сеанса в процессе, внешний его в распределенный кэш, например Redis или базу данных, например Azure SQL Server.

  • Настройте правила автомасштабирования. Используйте конфигурации автомасштабирования, которые обеспечивают наиболее экономичный контроль над службами. Для контейнерных служб масштабирование на основе событий, таких как автомасштабирование на основе событий Kubernetes (KEDA), часто обеспечивает детализированный контроль, позволяющий масштабироваться на основе метрик событий. Приложения контейнеров Azure и Служба Azure Kubernetes поддерживают KEDA. Для служб, которые не поддерживают KEDA, такие как служба приложение Azure, используйте функции автомасштабирования, предоставляемые самой платформой. Эти функции часто включают масштабирование на основе правил на основе метрик или HTTP-трафика.

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

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

  • Настройте масштабирование на основе очередей. Если приложение использует очередь сообщений, например Служебная шина Azure, настройте параметры автомасштабирования для масштабирования на основе длины очереди с сообщениями запроса. Масштабировщик предназначен для поддержания одной реплики службы для каждого N-сообщения в очереди (округлено).

Например, эталонная реализация использует масштабировщик KEDA Служебная шина Azure для масштабирования приложения-контейнера на основе длины очереди. Служба service-bus-queue-length-rule масштабируется на основе длины указанной очереди Служебная шина Azure. Параметр messageCount имеет значение 10, поэтому масштабировщик имеет одну реплику службы для каждых 10 сообщений в очереди. scaleMinReplicas Параметры scaleMaxReplicas задают максимальное и минимальное количество реплик для службы. Секретqueue-connection-string, содержащий строка подключения для очереди служебная шина, извлекается из Key Vault. Этот секрет используется для проверки подлинности масштабировщика в служебная шина.

scaleRules: [
  {
    name: 'service-bus-queue-length-rule'
    custom: {
      type: 'azure-servicebus'
      metadata: {
        messageCount: '10'
        namespace: renderRequestServiceBusNamespace
        queueName: renderRequestServiceBusQueueName
      }
      auth: [
        {
          secretRef: 'render-request-queue-connection-string'
          triggerParameter: 'connection'
        }
      ]
    }
  }
]

scaleMaxReplicas: 5
scaleMinReplicas: 0

Развертывание службы containerize

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

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

  • Создание образов docker. При создании образов Docker для служб .NET используйте базовые образы. Эти образы содержат только минимальный набор пакетов, необходимых для запуска .NET, что сводит к минимуму размер пакета и область области атаки.

  • Используйте многоэтапные файлы Dockerfile. Реализуйте многоэтапные файлы Dockerfile для разделения ресурсов во время сборки от образа контейнера среды выполнения. Это помогает сохранить рабочие образы небольшими и безопасными.

  • Запуск от имени пользователя, не являемого пользователем. Запустите контейнеры .NET в качестве пользователя, не являющегося пользователем (с помощью имени пользователя или UID, $APP_UID), чтобы соответствовать принципу наименьших привилегий. Он ограничивает потенциальные последствия скомпрометированного контейнера.

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

  • Инкапсулировать зависимости. Убедитесь, что все зависимости для функции приложения инкапсулируются в образе контейнера Docker. Инкапсуляция позволяет приложению надежно развертываться в широком диапазоне узлов.

  • Выберите правильные базовые изображения. Выбранный базовый образ зависит от среды развертывания. Если вы развертываете приложения контейнеров Azure, например, необходимо использовать образы Linux Docker.

Например, эталонная реализация использует многоэтапный процесс сборки. Начальные этапы компиляции и сборки приложения с помощью полного образа пакета SDK (mcr.microsoft.com/dotnet/sdk:8.0-jammy). Окончательный образ среды выполнения создается из chiseled базового образа, который исключает пакет SDK и артефакты сборки. Служба выполняется как пользователь, отличный от сети (USER $APP_UID) и предоставляет порт 8080. Зависимости, необходимые для работы приложения, включаются в образ Docker, как показано командами для копирования файлов проекта и восстановления пакетов. Использование образов на основе Linux обеспечиваетmcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled совместимость с приложениями контейнеров Azure, для которых требуется контейнеры Linux для развертывания.

# Build in a separate stage to avoid copying the SDK into the final image
FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src

# Restore packages
COPY ["Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj", "Relecloud.TicketRenderer/"]
COPY ["Relecloud.Messaging/Relecloud.Messaging.csproj", "Relecloud.Messaging/"]
COPY ["Relecloud.Models/Relecloud.Models.csproj", "Relecloud.Models/"]
RUN dotnet restore "./Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj"

# Build and publish
COPY . .
WORKDIR "/src/Relecloud.TicketRenderer"
RUN dotnet publish "./Relecloud.TicketRenderer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

# Chiseled images contain only the minimal set of packages needed for .NET 8.0
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS final
WORKDIR /app
EXPOSE 8080

# Copy the published app from the build stage
COPY --from=build /app/publish .

# Run as non-root user
USER $APP_UID
ENTRYPOINT ["dotnet", "./Relecloud.TicketRenderer.dll"]

Развертывание эталонной реализации

Разверните эталонную реализацию шаблона современного веб-приложения для .NET. В репозитории приведены инструкции по разработке и рабочему развертыванию. После развертывания можно имитировать и наблюдать за шаблонами проектирования.

Схема, показывающая архитектуру эталонной реализацииРис. 3. Архитектура эталонной реализации. Скачайте файл Visio этой архитектуры.