Контейнерные микрослужбы

Примечание.

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

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

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

Monolithic application scaling approach

Рис. 8-1. Монолитный подход к масштабированию приложений

Микрослужбы

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

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

Diagram shows two apps with tiles representing different functional areas and six rectangles hosting various functional areas from both apps.

Рис. 8-2. Подход масштабирования приложений микрослужб

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

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

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

Поэтому приложения микрослужб имеют множество преимуществ по сравнению с монолитными приложениями:

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

Однако решение на основе микрослужб также имеет потенциальные недостатки:

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

Контейнеризация

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

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

Существует множество сходств между контейнерами и виртуальными машинами, как показано на рис. 8-3.

Diagram shows a comparison between Virtual Machines and Containers, where virtual machines have three apps each siloed on a guest O S, with a hypervisor and a host O S, and the containers have three apps hosted in a container engine on a single OS.

Рис. 8-3. Сравнение виртуальных машин и контейнеров

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

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

Основные понятия при создании и работе с контейнерами:

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

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

Эталонное приложение eShopOnContainers использует Docker для размещения четырех контейнерных микрослужб, как показано на рис. 8-4.

eShopOnContainers reference application back-end microservices

Рис. 8-4. Справочные микрослужбы приложений eShopOnContainers

Архитектура внутренних служб в эталонном приложении разложена в несколько автономных подсистем в виде совместной работы микрослужб и контейнеров. Каждая микрослужба предоставляет одну область функциональности: службу удостоверений, службу каталога, службу заказа и службу корзины.

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

Дополнительные сведения о эталонных приложениях см. в разделе микрослужб .NET: архитектура для контейнерных приложений .NET.

Обмен данными между клиентами и микрослужбами

Мобильное приложение eShopOnContainers взаимодействует с контейнерными внутренними микрослужбами с помощью прямой связи между клиентами и микрослужбами , показанной на рис. 8-5.

Diagram shows an app hosted on a mobile device connected to three Backend Microservices, each with its own Web A P I Container.

Рис. 8-5. Прямая связь между клиентами и микрослужбами

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

Совет

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

Обмен данными между микрослужбами

Приложение на основе микрослужб — это распределенная система, потенциально работающая на нескольких компьютерах. Обычно каждый экземпляр службы — это процесс. Поэтому службы должны взаимодействовать с использованием протокола обмена данными между процессами, таких как HTTP, TCP, расширенный протокол очереди сообщений (AMQP) или двоичные протоколы в зависимости от характера каждой службы.

Два распространенных подхода к обмену данными микрослужбы — это взаимодействие REST на основе HTTP при запросе данных и упрощенное асинхронное обмен сообщениями при обмене обновлениями между несколькими микрослужбами.

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

Шина событий позволяет публиковать и подписываться между микрослужбами, не требуя явного учета компонентов друг друга, как показано на рис. 8-6.

Publish-subscribe with an event bus

Рис. 8-6. Публикация подписки на шину событий

С точки зрения приложения шина событий — это просто канал публикации подписки, предоставляемый через интерфейс. Однако способ реализации шины событий может отличаться. Например, реализация шины событий может использовать RabbitMQ, Служебная шина Azure или другие служебные автобусы, такие как NServiceBus и MassTransit. На рисунке 8-7 показано, как шина событий используется в справочном приложении eShopOnContainers.

Asynchronous event-driven communication in the reference application

Рис. 8-7. Асинхронное взаимодействие на основе событий в эталонном приложении

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

One-to-many communication

Рис. 8-9. Связь "один ко многим"

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

Примечание.

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

Сведения о реализации шины событий см. в разделе Микрослужбы .NET: архитектура для контейнерных приложений .NET.

Итоги

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

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