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

Служба приложений Azure
Служебная шина Azure

В этой статье описывается, как реализовать шаблон современного веб-приложения. Шаблон современного веб-приложения определяет, как модернизировать облачные веб-приложения и внедрить архитектуру, ориентированную на обслуживание. Шаблон предоставляет предписательную архитектуру, код и рекомендации по настройке, которые соответствуют принципам Azure Well-Architected Framework. Этот шаблон основан на шаблоне Reliable Web App.

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

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

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

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

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

Совет

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

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

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

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

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

схема с архитектурой шаблона современного веб-приложения со вторым регионом.

Разделение архитектуры

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Каждый шаблон проектирования предоставляет преимущества, которые соответствуют одному или нескольким основным элементам платформы Well-Architected Framework. В следующей таблице приведены сведения.

Конструктивный шаблон Расположение реализации Надежность (RE) Безопасность (SE) Оптимизация затрат (CO) Операционное превосходство (OE) Эффективность производительности (PE) Поддержка принципов хорошо спроектированной платформы
Шаблон 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 в новую службу.

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

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

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

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

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

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

  • Используйте очередь сообщений без блокировки. Убедитесь, что процесс, отправляющий сообщения в очередь, не блокирует другие процессы во время ожидания отсоединяемой службы для обработки сообщений в очереди. Если для процесса требуется результат операции отсоединяемой службы, реализуйте альтернативный способ обработки ситуации, ожидая завершения операции в очереди. Например, в Spring Boot можно использовать класс StreamBridge для асинхронной публикации сообщений в очередь без блокировки вызывающего потока:

    private final StreamBridge streamBridge;
    
    public SupportGuideQueueSender(StreamBridge streamBridge) {
        this.streamBridge = streamBridge;
    }
    
    // Asynchronously publish a message without blocking the calling thread
    @Override
    public void send(String to, String guideUrl, Long requestId) {
        EmailRequest emailRequest = EmailRequest.newBuilder()
                .setRequestId(requestId)
                .setEmailAddress(to)
                .setUrlToManual(guideUrl)
                .build();
    
        log.info("EmailRequest: {}", emailRequest);
    
        var message = emailRequest.toByteArray();
        streamBridge.send(EMAIL_REQUEST_QUEUE, message);
    
        log.info("Message sent to the queue");
    }
    

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

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

  • Настройте идемпотентную обработку сообщений. Логика, обрабатывающая сообщения из очереди, должна быть идемпотентной для обработки случаев, в которых сообщение может обрабатываться несколько раз. В Spring Boot можно использовать или @StreamListener с @KafkaListener уникальным идентификатором сообщения, чтобы предотвратить повторную обработку. Или можно упорядочить бизнес-процесс для работы в функциональном подходе с Spring Cloud Stream, где consume метод определяется таким образом, что приводит к тому же результату при многократном выполнении. Список параметров, которые управляют поведением потребления сообщений, см. в разделе Spring Cloud Stream сслужебной шины.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@Configuration
public class EmailProcessor {

    private static final Logger log = LoggerFactory.getLogger(EmailProcessor.class);

    @Bean
    Function<byte[], byte[]> consume() {
        return message -> {

            log.info("New message received");

            try {
                EmailRequest emailRequest = EmailRequest.parseFrom(message);
                log.info("EmailRequest: {}", emailRequest);

                EmailResponse emailResponse = EmailResponse.newBuilder()
                        .setEmailAddress(emailRequest.getEmailAddress())
                        .setUrlToManual(emailRequest.getUrlToManual())
                        .setRequestId(emailRequest.getRequestId())
                        .setMessage("Email sent to " + emailRequest.getEmailAddress() + " with URL to manual " + emailRequest.getUrlToManual())
                        .setStatus(Status.SUCCESS)
                        .build();

                return emailResponse.toByteArray();

            } catch (InvalidProtocolBufferException e) {
                throw new RuntimeException("Error parsing email request message", e);
            }
        };
    }
}

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

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

  • Реализуйте проверки работоспособности. Используйте Spring Boot Actuator для предоставления конечных точек проверки работоспособности. Actuator предоставляет конечную точку /actuator/health, которая включает встроенные индикаторы работоспособности и пользовательские проверки для различных зависимостей. Чтобы включить конечную точку работоспособности, добавьте зависимость spring-boot-starter-actuator в файл pom.xml или build.gradle:

    <!-- Add Spring Boot Actuator dependency -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    

    Настройте конечную точку работоспособности в application.properties, как показано в эталонной реализации:

        management.endpoints.web.exposure.include=metrics,health,info,retry,retryevents
    
  • Проверка зависимостей. Spring Boot Actuator включает индикаторы работоспособности для различных зависимостей, таких как базы данных, брокеры сообщений (RabbitMQ или Kafka) и службы хранения. Чтобы проверить доступность служб Azure, таких как хранилище BLOB-объектов Azure или служебная шина, используйте такие технологии, как Azure Spring Apps или Micrometer, которые предоставляют индикаторы работоспособности для этих служб. Если вам нужны пользовательские проверки, их можно реализовать, создав настраиваемую HealthIndicator bean:

    import org.springframework.boot.actuate.health.Health;
    import org.springframework.boot.actuate.health.HealthIndicator;
    import org.springframework.stereotype.Component;
    
    @Component
    public class CustomAzureServiceBusHealthIndicator implements HealthIndicator {
        @Override
        public Health health() {
            // Implement your health check logic here (for example, ping Service Bus).
            boolean isServiceBusHealthy = checkServiceBusHealth();
            return isServiceBusHealthy ? Health.up().build() : Health.down().build();
        }
    
        private boolean checkServiceBusHealth() {
            // Implement health check logic (pinging or connecting to the service).
            return true; // Placeholder. Implement the actual logic.
        }
    }
    
  • Настройте ресурсы Azure. Настройте ресурс Azure для использования URL-адресов проверки работоспособности приложения для подтверждения активности и готовности. Например, вы можете использовать Terraform для подтверждения активности и готовности приложений, развернутых в контейнерных приложениях. Дополнительные сведения см. в разделе "Пробы работоспособности" в контейнерных приложениях.

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

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

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

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

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

  • Используйте стандартные библиотеки устойчивости для HTTP-клиентов. Для http-клиентов можно использовать устойчивость4j вместе с RestTemplate или WebClient Spring для обработки повторных попыток в связи с HTTP. Вы можете упаковать RestTemplate с логикой повторных попыток отказоустойчивости4j, чтобы эффективно обрабатывать временные ошибки HTTP.

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

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

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

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

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

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

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

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

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

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

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

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

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

resource "azurerm_role_assignment" "container_app_acr_pull" {
  principal_id         = var.aca_identity_principal_id
  role_definition_name = "AcrPull"
  scope                = azurerm_container_registry.acr.id
}

resource "azurerm_user_assigned_identity" "container_registry_user_assigned_identity" {
  name                = "ContainerRegistryUserAssignedIdentity"
  resource_group_name = var.resource_group
  location            = var.location
}

resource "azurerm_role_assignment" "container_registry_user_assigned_identity_acr_pull" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "AcrPull"
  principal_id         = azurerm_user_assigned_identity.container_registry_user_assigned_identity.principal_id
}


# For demo purposes, allow the current user to access the container registry.
# Note: When running as a service principal, this is also needed.
resource "azurerm_role_assignment" "acr_contributor_user_role_assignement" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "Contributor"
  principal_id         = data.azuread_client_config.current.object_id
}

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

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

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

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

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

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

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

Например, эталонная реализация использует масштабировщик KEDA служебная шина для автоматического масштабирования приложения-контейнера на основе длины очереди служебная шина. Правило масштабирования с именем service-bus-queue-length-ruleнастраивает количество реплик служб на основе количества сообщений в указанной очереди служебной шины. Параметр messageCount имеет значение 10, что настраивает масштабировщик для добавления одной реплики для каждых 10 сообщений в очереди. Максимальное число реплик (max_replicas) имеет значение 10. Минимальное число реплик неявно равно 0, если оно не переопределено. Эта конфигурация позволяет службе уменьшить до нуля, если в очереди нет сообщений. Строка подключения для очереди служебной шины хранится в виде секрета в Azure с именем azure-servicebus-connection-string, которая используется для проверки подлинности масштабировщика в служебной шине. Ниже приведен код Terraform:

    max_replicas = 10
    min_replicas = 1

    custom_scale_rule {
      name             = "service-bus-queue-length-rule"
      custom_rule_type = "azure-servicebus"
      metadata = {
        messageCount = 10
        namespace    = var.servicebus_namespace
        queueName    = var.email_request_queue_name
      }
      authentication {
        secret_name       = "azure-servicebus-connection-string"
        trigger_parameter = "connection"
      }
    }

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

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

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

  • Создание образов Docker. При создании образов Docker для служб Java используйте официальные базовые образы OpenJDK. Эти образы содержат только минимальный набор пакетов, которые должен выполнять Java. Использование этих образов сводит к минимуму размер пакета и область области атаки.

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

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

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

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

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

Эталонная реализация демонстрирует процесс сборки Docker для контейнеризации приложения Java. Dockerfile использует одноэтапную сборку с базовым образом OpenJDK (mcr.microsoft.com/openjdk/jdk:17-ubuntu), который предоставляет необходимую среду выполнения Java.

Dockerfile включает следующие действия.

  1. Объявление тома. Определяется временный том (/tmp). Этот том предоставляет временное хранилище файлов, отдельное от основной файловой системы контейнера.
  2. Копирование артефактов. JAR-файл приложения (email-processor.jar) копируется в контейнер вместе с агентом Application Insights (applicationinsights-agent.jar), который используется для мониторинга.
  3. Задание точки входа. Контейнер настроен для запуска приложения с включенным агентом Application Insights. Код использует java -javaagent для мониторинга приложения во время выполнения.

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

# Use the OpenJDK 17 base image on Ubuntu as the foundation.
FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu

# Define a volume to allow temporary files to be stored separately from the container's main file system.
VOLUME /tmp

# Copy the packaged JAR file into the container.
COPY target/email-processor.jar app.jar

# Copy the Application Insights agent for monitoring.
COPY target/agent/applicationinsights-agent.jar applicationinsights-agent.jar

# Set the entrypoint to run the application with the Application Insights agent.
ENTRYPOINT ["java", "-javaagent:applicationinsights-agent.jar", "-jar", "/app.jar"]

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

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

На следующей схеме показана архитектура эталонной реализации:

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

Скачайте файл Visio этой архитектуры.