Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
Чтобы вам было проще приступить к работе, в руководстве подробно изучается пример контейнерного
приложения на основе микрослужб. Образец приложения доступен в репозитории GitHub
eShopOnContainers.
Ссылки действий
Эта электронная книга также доступна в формате PDF (только на английском языке) Скачать
Клонировать эталонное приложение eShopOnContainers на GitHub или создать для него вилку
Вступление
Предприятия все шире применяют контейнеры с целью сэкономить средства, решить проблемы,
возникающие при разработке решений, и оптимизировать процессы разработки и рабочие операции.
Корпорация Майкрософт развивает технологии в области контейнеров для Windows и Linux, создавая
такие продукты, как Служба Azure Kubernetes и Azure Service Fabric, и сотрудничая с ведущими в отрасли
компаниями, такими как Docker, Mesosphere и Kubernetes. С помощью этих решений для работы с
контейнерами организации могут создавать и развертывать приложения с той же скоростью и
масштабируемостью, что и в облачной среде, на основе любых платформ и средств.
Помимо этого, развивается архитектура микрослужб, которая представляет собой важный подход к
реализации распределенных критически важных приложений. Архитектура на основе микрослужб
предполагает создание приложения на базе коллекции служб, которые могут разрабатываться,
тестироваться, развертываться и обновляться независимо друг от друга.
Об этом руководстве
В этом руководстве приводятся общие сведения о разработке приложений на основе микрослужб и
управлении ими с помощью контейнеров. В нем рассматриваются подходы к проектированию и
реализации архитектуры с использованием .NET и контейнеров Docker. Чтобы вам было проще
приступить к работе с контейнерами и микрослужбами, в руководстве подробно изучается пример
контейнерного приложения на основе микрослужб. Пример приложения доступен в репозитории GitHub
eShopOnContainers.
В этом руководстве приведены базовые принципы разработки и архитектуры, в первую очередь — на
уровне среды разработки. Основное внимание уделяется двум технологиям: Docker и .NET. Мы ставили
себе целью, чтобы при чтении этого руководства вы могли сосредоточиться на проектировании
приложения, не задумываясь об инфраструктуре рабочей среды (облачной или локальной). Принимать
решения, связанные с инфраструктурой, вы будете позднее при создании приложений, готовых к
использованию в рабочей среде. Таким образом, это руководство ориентировано на среду разработки
без учета особенностей инфраструктуры.
После изучения этого руководства вашим следующим шагом будет изучение готовых к использованию
микрослужб в Microsoft Azure.
Version
В новую редакцию руководства включены сведения о версии .NET 5 и множество дополнений, связанных
с тем же "поколением" технологий (т. е. технологий Azure и сторонних производителей), к которому
относится выпуск .NET 5. По этой причине версия книги также была изменена на 5.0 .
Дополнительные ресурсы
Containerized Docker Application Lifecycle with Microsoft Platform and Tools (Жизненный цикл
контейнерного приложения Docker на основе платформы и средств Майкрософт ) (электронная книга,
доступная для скачивания)
https://aka.ms/dockerlifecycleebook
Руководство также может оказаться полезным для лиц, принимающих технические решения, например
архитекторов корпоративных систем, которым необходимо получить общие сведения об архитектуре и
технологиях, прежде чем выбирать подход для создания современных распределенных приложений.
Вторая часть руководства начинается с раздела Процесс разработки для приложений на основе Docker.
Он посвящен разработке и шаблонам микрослужб для реализации приложений с помощью .NET и Docker.
Этот раздел будет особенно интересен разработчикам и архитекторам, которым нужны подробные
сведения о реализации на уровне кода и шаблона.
Это приложение предназначено для демонстрации архитектурных шаблонов. ЭТОТ ШАБЛОН НЕЛЬЗЯ
РАССМАТРИВАТЬ КАК ГОТОВУЮ К ЗАПУСКУ ОСНОВУ для реальных приложений. По сути это
приложение постоянно находится в состоянии бета-версии и используется для тестирования новых
интересных технологий по мере их появления.
Благодарности
Соавторы:
Сезар де ла Торре (Cesar de la Torre) , старший руководитель проекта, команда разработки .NET,
корпорация Майкрософт.
Билл Вэгнер (Bill Wagner) , старший разработчик содержимого, отдел C+E, корпорация
Майкрософт.
Майк Роусос (Mike Rousos), главный специалист по разработке программного обеспечения, команда
DevDiv CAT, корпорация Майкрософт
Редакторы:
Участники и рецензенты:
Уди Дахан (Udi Dahan), основатель и генеральный директор компании Particular Software
Марк Фасселл (Mark Fussell), ведущий руководитель проектов, команда Azure Service Fabric,
корпорация Майкрософт
Диего Вега (Diego Vega), руководитель проектов, команда Entity Framework, корпорация
Майкрософт
Анкит Астана (Ankit Asthana), ведущий руководитель проектов, команда .NET, корпорация
Майкрософт
Скотт Хантер (Scott Hunter), помощник главного руководителя проектов, команда .NET, корпорация
Майкрософт
Ниш Анил (Nish Anil) , старший менеджер программ, команда .NET, корпорация Майкрософт
Унаи Зоррилла (Unai Zorrilla), архитектор и руководитель разработки, компания Plain Concepts
Copyright
ИЗДАТЕЛЬ
Эта книга предоставляется на условиях "как есть" и выражает взгляды и мнения автора. Взгляды, мнения
и сведения, содержащиеся в этой книге, включая URL-адреса и другие ссылки на веб-сайты, могут
изменяться без уведомления.
Некоторые приведенные в книге примеры служат только для иллюстрации и являются вымышленными.
Все совпадения с реальными наименованиями, людьми и любыми другими предметами являются
непреднамеренными и случайными.
ВПЕРЕД
Общие сведения о контейнерах и Docker
02.11.2021 • 2 minutes to read
Контейнеризация — это подход к разработке программного обеспечения, при котором приложение или
служба, их зависимости и конфигурация (абстрактные файлы манифеста развертывания) упаковываются
вместе в образ контейнера. Контейнерное приложение может тестироваться как единое целое и
развертываться как экземпляр образа контейнера в операционной системе (ОС ) узла.
Так же как обычные контейнеры позволяют перевозить любые грузы на корабле, поезде или грузовике,
программные контейнеры выступают в качестве стандартных модулей для развертывания программного
обеспечения, которые могут содержать различный код и зависимости. Контейнеризация программного
обеспечения позволяет разработчикам и ИТ -специалистам развертывать его в разных средах без каких-
либо изменений или с минимальными изменениями.
Контейнеры также изолируют приложения друг от друга в общей операционной системе. Контейнерные
приложения выполняются на основе узла контейнеров, который в свою очередь работает в
операционной системе (Linux или Windows). Поэтому контейнеры требуют гораздо меньше ресурсов, чем
образы виртуальных машин.
Каждый контейнер может вмещать целое веб-приложение или службу, как показано на рис. 2-1. В этом
примере узел Docker — это узел контейнеров, а App1, App2, Svc 1 и Svc 2 — контейнерные приложения
или службы.
Иными словами, контейнеры предоставляют такие преимущества, как изоляция, переносимость, гибкость,
масштабируемость и контроль, на протяжении всего жизненного цикла приложения. Самым важным
преимуществом является изоляция среды разработки от рабочей среды.
НА ЗА Д ВПЕРЕД
Что такое Docker?
02.11.2021 • 4 minutes to read
Docker — это проект с открытым исходным кодом для автоматизации развертывания приложений в виде
переносимых автономных контейнеров, выполняемых в облаке или локальной среде. Одновременно с
этим, Docker — это компания, которая разрабатывает и продвигает эту технологию в сотрудничестве с
поставщиками облачных служб, а также решений Linux и Windows, включая корпорацию Майкрософт.
Контейнеры Docker могут работать в любой среде, например в локальном центре обработки данных, в
службе стороннего поставщика или в облаке Azure. Контейнеры образов Docker работают в исходном
формате в Linux и Windows. Но образы Windows будут выполняться только на узлах Windows, тогда как
образы Linux — на узлах Linux или Windows (на данный момент с помощью виртуальной машины Linux
Hyper-V). Термин "узлы" здесь означает физические серверы и виртуальные машины.
Разработчики могут использовать среды разработки на базе Windows, Linux или macOS. На компьютере
разработчика выполняется узел Docker, где развернуты образы Docker с создаваемым приложением и
всеми его зависимостями. Разработчики, работающие в Linux или macOS, могут использовать узел Docker
на базе Linux и создавать образы только для контейнеров Linux. (В macOS разработчики могут изменять
код приложения и запускать Docker CLI в macOS, но на момент написания этой статьи они не могут
запускать контейнеры непосредственно в macOS.) В Windows разработчики могут создавать образы для
контейнеров Linux или Windows.
Docker предоставляет Docker Desktop для Windows и macOS, позволяя размещать контейнеры в среде
разработки и использовать дополнительные средства разработки. Оба продукта устанавливают
необходимую виртуальную машину (узел Docker) для размещения контейнеров.
Образы для этих контейнеров создаются и работают одинаково. Различие заключается лишь в том, что
для создания контейнера из образа с контейнером Hyper-V нужен дополнительный параметр.
Дополнительные сведения см. в разделе Контейнеры Hyper-V.
Виртуальные машины содержат приложение, Контейнеры включают в себя приложение и все его
необходимые библиотеки или двоичные файлы и всю зависимости. Но они используют ядро ОС совместно с
операционную систему. Полная виртуализация требует другими контейнерами, которые выполняются в
больше ресурсов, чем создание контейнеров. изолированных процессах в пользовательском
пространстве операционной системы узла. (Это не
относится к контейнерам Hyper-V, где каждый
контейнер запускается на отдельной виртуальной
машине.)
Для виртуальных машин на сервере узла создается три базовых уровня: самый нижний
инфраструктурный слой; затем операционная система узла и низкоуровневая оболочка; и поверх этого
каждая виртуальная машина использует собственную ОС и все необходимые библиотеки. Для Docker
сервер узла предоставляет только инфраструктуру и операционную систему, а также ядро контейнеров,
которое изолирует контейнер с использованием базовых служб операционной системы.
Так как контейнеры требуют гораздо меньше ресурсов (например, им не нужна полная ОС ), их проще
развертывать и они быстрее запускаются. Это позволяет повысить плотность развертываний, то есть
запустить на одной единице оборудования больше служб и сократить затраты на них.
Запуск на одном ядре приводит к тому, что уровень изоляции будет ниже, чем на виртуальных машинах.
Образ контейнера — это способ упаковки приложения или службы для надежного и воспроизводимого
развертывания. Можно сказать, что Docker является не только технологией, но еще философией и
процессом.
При работе с Docker разработчики никогда не жалуются, что приложение работает только на локальном
компьютере, но не в рабочей среде. Им достаточно сказать "Выполняется в Docker", так как упакованное
приложение Docker будет выполняться в любой поддерживаемой среде Docker. Оно будет работать
одинаково во всех сценариях развертывания (разработка, контроль качества, промежуточное
размещение и рабочая среда).
Простая аналогия
Возможно, небольшая аналогия поможет вам быстрее освоить ключевую концепцию Docker.
Вернемся ненадолго назад во времени, в 1950-е годы. Тогда еще не было текстовых редакторов, и
повсеместно использовались фотокопировальные устройства (то есть то, что тогда так называлось).
Представьте, что вам понадобилось быстро подготовить наборы писем, чтобы отправить их с обычной
бумажной почтой в настоящих конвертах с марками и доставить по домашнему адресу клиента (не
забывайте, еще не существует электронной почты).
В какой-то момент вы понимаете, что каждое письмо составлено из широкого набора абзацев, которые
выбираются и упорядочиваются по мере необходимости с учетом назначения письма. Вы создаете
систему, которая быстро создает нужные письма, и обоснованно надеетесь на существенную прибавку.
1. У вас есть пачка прозрачных листов, каждый из которых содержит один абзац.
2. Чтобы подготовить комплект писем, вы отбираете листы с нужными абзацами, собираете их в
стопку и выравниваете так, чтобы все правильно читалось.
В Docker каждый слой представляет некоторый набор изменений, которые применяются к файловой
системе после выполнения команды, такой как установка программы.
Если вы "посмотрите" на файловую систему после копирования очередного слоя, вы увидите все файлы в
том состоянии, которое они приняли после установки программы.
Такой образ можно рассматривать как дополнительный жесткий диск, доступный только для чтения,
который готов к установке на "компьютер" с уже установленной операционной системой.
НА ЗА Д ВПЕРЕД
Терминология Docker
02.11.2021 • 4 minutes to read
В этом разделе приводятся термины и определения, необходимые при работе с инструментом Docker. С
развернутыми определениями можно ознакомиться в глоссарии инструмента Docker.
Dockerfile : текстовый файл, содержащий инструкции по сборке образа Docker. Он похож на пакетный
сценарий, где первая строка указывает базовый образ, с которого начинается работа, а следующие
инструкции устанавливают необходимые программы, копируют файлы и т. п. для создания необходимой
рабочей среды.
docker build
Контейнер: экземпляр образа Docker. Контейнер отвечает за выполнение одного приложения, процесса
или службы. Он состоит из содержимого образа Docker, среды выполнения и стандартного набора
инструкций. При масштабировании службы вы создаете несколько экземпляров контейнера из одного
образа. Или пакетное задание может создать несколько контейнеров из одного образа, передавая
разные параметры каждому экземпляру.
Тома : предложите файловую систему с возможностью записи, которую может использовать этот
контейнер. Поскольку образы доступны только для чтения, а большинству программ требуется
возможность записи в файловую систему, тома добавляют слой с поддержкой записи поверх образа
контейнера, который программы смогут использовать как файловую систему с возможностью записи.
Программа не знает , что она обращается к многоуровневой файловой системе. Для нее это обычный
вызов файловой системы. Тома размещаются в системе узла под управлением Docker.
Тег: метка для образа, которая позволяет различать разные образы или версии одного образа (в
зависимости от номера версии или целевой среды).
Многоэтапная сборка : этот компонент входит в Docker, начиная с версии 17.05, и позволяет сократить
итоговый размер образов. Если попытаться кратко описать эту функцию, многоэтапная сборка
позволяет использовать крупный базовый образ с пакетом SDK для компиляции и публикации
приложения, а затем создать итоговый образ намного меньшего размера с помощью небольшого
базового образа для среды выполнения, размещенного в папке публикации.
Репозиторий: коллекция связанных образов Docker, помеченная тегом, указывающим на версию образа.
Некоторые репозитории содержат несколько вариантов одного образа, например образ с пакетом
средств разработки (больший объем), образ только со средой выполнения (меньший объем) и т. д. Эти
варианты можно пометить тегами. Один репозиторий может содержать варианты платформ, например
образ Linux и образ Windows.
Мультиархитектурный образ: Для нескольких архитектур это функция, которая упрощает выбор
соответствующего образа в соответствии с платформой, в которой работает Docker. Например, когда
Dockerfile запрашивает базовый образ mcr.microsoft.com/dotnet/sdk :5.0 из реестра, фактически
возвращается 5.0-nanoser ver-1909 , 5.0-nanoser ver-1809 или 5.0-buster-slim (в зависимости от ОС и
версии среды, в которой работает Docker).
Центр Docker : общедоступный реестр для загрузки образов и работы с ними. Центр Docker
обеспечивает размещение образов Docker и интеграцию с GitHub и Bitbucket, предоставляет
общедоступные или частные реестры, триггеры сборки и веб-перехватчики.
Реестр контейнеров Azure : общедоступный ресурс для работы с образами Docker и их компонентами
в Azure. Он предоставляет реестр, близкий к вашим развертываниям в Azure, так что вы можете
контролировать доступ и использовать группы и разрешения в Azure Active Directory.
Доверенный реестр Docker (DTR) : служба реестра Docker (из Docker), которую можно установить
локально, чтобы она находилась в центре данных и сети организации. Его удобно использовать для
частных образов, которыми необходимо управлять внутри предприятия. Доверенный реестр Docker
входит в Центр данных Docker. Дополнительные сведения см. в разделе Доверенный реестр Docker (DTR).
Docker Community Edition (CE) : инструменты разработки в среде Windows и macOS для локальной
сборки, выполнения и тестирования контейнеров. Docker CE для Windows предоставляет среды
разработки для контейнеров Linux и Windows. Узел Linux Docker на Windows базируется на виртуальной
машине Hyper-V. Узел для контейнеров Windows базируется непосредственно на Windows. Docker CE для
Mac базируется на платформе Apple Hypervisor и гипервизоре xhyve, который предоставляет узлу Linux
Docker виртуальную машину в macOS X. Docker CE для Windows и для Mac заменил Docker Toolbox на базе
Oracle VirtualBox.
Docker Enterprise Edition (EE) : корпоративная версия инструментов Docker для разработки в среде
Windows и Linux.
Compose : программа командной строки и формат файлов YAML с метаданными для определения и
выполнения многоконтейнерных приложений. Вы определяете одно приложение на основе нескольких
образов с помощью одного или нескольких файлов .yml, которые могут изменять значения в зависимости
от среды. Создав определения, вы можете развернуть все многоконтейнерное приложение с помощью
одной команды (docker-compose up), которая создает один контейнер на образ на узле Docker.
Кластер: коллекция узлов Docker, представленная в виде единого виртуального узла Docker, чтобы
можно было масштабировать приложение в нескольких экземплярах служб, распределенных по
нескольким узлам кластера. Кластеры Docker можно создавать с помощью Kubernetes, Azure Service
Fabric, Docker Swarm и (или) Mesosphere DC/OS.
Оркестратор: инструмент , упрощающий управление кластерами и узлами Docker. С помощью
оркестраторов можно управлять образами, контейнерами и узлами через интерфейс командной строки
(CLI) или графический интерфейс. Вы можете управлять соединениями контейнеров, конфигурациями,
балансировкой нагрузки, обнаружением служб, высоким уровнем доступности, конфигурацией узлов
Docker и многим другим. Оркестратор используется для выполнения, распределения, масштабирования и
восстановления рабочих нагрузок в коллекции узлов. В качестве оркестраторов обычно используются те
же продукты, которые обеспечивают кластерную инфраструктуру, например Kubernetes и Azure Service
Fabric (на рынке доступны и другие предложения).
НА ЗА Д ВПЕРЕД
Контейнеры, образы и реестры Docker
02.11.2021 • 2 minutes to read
При использовании Docker разработчик создает приложение или службу и упаковывает приложение или
службу и их зависимости в образ контейнера. Образ — это статическое представление приложения или
службы, а также их конфигурации и зависимостей.
Для запуска приложения или службы создается экземпляр образа приложения, чтобы создать контейнер,
который будет запущен на узле Docker. Контейнеры изначально проверяются в среде разработки или на
ПК.
Разработчикам следует хранить образы в реестре, который выступает в качестве библиотеки образов и
необходим при развертывании на оркестраторы в рабочей среде. Docker поддерживает общедоступный
реестр с помощью Docker Hub. Другие поставщики предлагают реестры для различных коллекций
образов, включая Реестр контейнеров Azure. Кроме того, организации могут развернуть локальные
частные реестры для своих образов Docker.
На рисунке 2-4 показано, как образы и реестры в Docker связаны с другими компонентами. На нем также
показано несколько вариантов реестра от поставщиков.
Реестр напоминает книжную полку. В нем хранятся образы, которые можно извлекать для создания
контейнеров, необходимых для запуска служб или веб-приложений. Частные реестры Docker могут
храниться в локальной среде или в общедоступном облаке. Docker Hub — это общедоступный реестр,
поддерживаемый Docker. Помимо решения Docker Trusted Registry корпоративного уровня можно
использовать Реестр контейнеров Azure, предлагаемый Azure. AWS, Google и другие компании также
предлагают свои реестры контейнеров.
Ваши образы не могут быть открыты для общего доступа по соображениям конфиденциальности.
Вам необходимо обеспечить минимальную сетевую задержку между образами и выбранной средой
развертывания. Например, если рабочая среда представляет собой облако Azure, вы, вероятно,
захотите разместить образы в Реестре контейнеров Azure, чтобы сетевая задержка была
минимальной. Точно так же, если рабочая среда является локальной, вы можете развернуть
локальный доверенный реестр Docker в той же локальной сети.
НА ЗА Д ВПЕРЕД
Выбор между .NET 5 и .NET Framework для
контейнеров Docker
02.11.2021 • 2 minutes to read
Серверные контейнерные приложения Docker можно разрабатывать на двух платформах .NET: .NET
Framework и .NET 5. В них используется множество одинаковых компонентов платформы .NET, а код
можно использовать как в одной среде, так и в другой. Но между этими двумя платформами также
существуют и фундаментальные различия. Поэтому ваш выбор будет зависеть от поставленной задачи.
В этом разделе приводятся рекомендации по выбору каждой из платформ.
НА ЗА Д ВПЕРЕД
Общие рекомендации
02.11.2021 • 2 minutes to read
В этом разделе представлена сводка относительно выбора .NET 5 или .NET Framework. Дополнительные
сведения об этих вариантах представлены в последующих разделах.
Используйте .NET 5 с контейнерами Windows или Linux для контейнерного серверного приложения
Docker в следующих случаях:
для создания кроссплатформенных решений; Например, вы хотите использовать контейнеры и
Windows, и Linux.
Архитектура приложения основана на микрослужбах.
Вам нужно быстро запустить контейнеры, и вы хотите использовать небольшой объем памяти на
каждый контейнер, чтобы получить более высокую плотность или больше контейнеров на
единицу оборудования для снижения затрат.
Вкратце, при создании новых контейнерных приложений .NET следует рассматривать .NET 5 как вариант
по умолчанию. Он имеет множество преимуществ и лучше соответствует концепции и стилю работы с
контейнерами.
Используйте .NET Framework для серверных приложений в контейнерах Docker в следующих случаях.
Требуются сторонние библиотеки .NET или пакеты NuGet, недоступные для .NET 5.
Использование .NET Framework в Docker может улучшить качество развертывания, сводя к минимуму
проблемы развертывания. Данный сценарий "подъема и смены" важен для контейнеризации приложений
прежних версий, которые изначально были разработаны с использованием классической платформы
.NET Framework, например ASP.NET WebForms, веб-приложений MVC или служб WCF (Windows
Communication Foundation).
Дополнительные ресурсы
Электронная книга. модернизация существующих приложений .NET Framework с
помощью Azure и контейнеров Windows
https://aka.ms/liftandshiftwithcontainersebook
Примеры приложений: модернизация устаревших веб- приложений ASP.NET с
помощью контейнеров Windows
https://aka.ms/eshopmodernizing
НА ЗА Д ВПЕРЕД
Выбор .NET для контейнеров Docker
02.11.2021 • 3 minutes to read
Благодаря модульности и упрощенному характеру .NET 5 идеально подходит для контейнеров. При
развертывании и запуске контейнера размер его образа гораздо меньше в среде .NET 5. Напротив, при
использовании .NET Framework для контейнера необходимо использовать Windows Server Core в
качестве базового образа, который занимает гораздо больше места, чем образ Nano Windows Server или
Linux, которые используются для .NET 5.
Кроме того, платформа .NET 5 является кроссплатформенной, поэтому вы можете разворачивать
серверные приложения в Linux и Windows контейнерах. Однако при использовании традиционной
.NET Framework можно развернуть только образ, основанный на Windows Server Core.
Ниже более подробно описаны преимущества .NET 5.
.NET 5 также поддерживает macOS в качестве платформы разработки. Тем не менее при развертывании
контейнеров на узле Docker этот узел должен (в настоящее время) базироваться на Windows или Linux.
Например, в среде разработки можно использовать виртуальную машину с Linux, запущенную на
компьютере с Mac.
Visual Studio предоставляет интегрированную среду разработки (IDE) для Windows и поддерживает
разработку с использованием Docker.
Visual Studio для Mac — это интегрированная среда разработки, которая является эволюцией Xamarin
Studio, выполняется в macOS и поддерживает разработку приложений на основе Docker. Этот инструмент
должен быть предпочтительным вариантом для разработчиков, которые работают на компьютерах с
Mac и хотят использовать мощную интегрированную среду разработки.
Редактор Visual Studio Code можно также использовать в macOS, Linux и Windows. Visual Studio Code
полностью поддерживает .NET 5, включая технологию IntelliSense и отладку. Так как VS Code является
упрощенным редактором, для разработки контейнерных приложений на компьютере его можно
использовать в сочетании с Docker CLI и .NET CLI. Для разработки на платформе .NET 5 также можно
использовать большинство сторонних редакторов, например Sublime, Emacs, vi и проект с открытым
кодом OmniSharp, который также поддерживает технологию IntelliSense.
С другой стороны, .NET 5 благодаря упрощенному характеру является наилучшим выбором, если вы
используете ориентированную на микрослужбы систему, которая основана на контейнерах. Кроме того,
связанные с NET Core образы, как для Linux, так и для Windows Nano Server, являются компактными и
небольшими по размеру, что обеспечивает их быстрый запуск.
Термин "микрослужба" означает , что она должна быть настолько маленькой, насколько это возможно,
чтобы обеспечивать быстрое развертывание, занимать мало места в памяти (см. статью о проблемно-
ориентированном проектировании), решать небольшую часть задачи и быть способной к быстрому
запуску и остановке. Для выполнения этих требований необходимо использовать небольшой и быстро
создаваемый образ контейнера, такой как образ контейнера .NET 5.
Это особенно важно для архитектур микрослужб, где могут выполняться сотни
микрослужб (контейнеров). Образы ASP.NET Core (основанные на среде выполнения .NET) на Windows
Nano или Linux позволяют запустить систему с гораздо меньшим количеством серверов или виртуальных
машин и, в конечном счете, снизить затраты на инфраструктуру и размещение.
НА ЗА Д ВПЕРЕД
Выбор .NET Framework для контейнеров Docker
02.11.2021 • 3 minutes to read
Хотя среда .NET 5 предоставляет значительные преимущества для новых приложений и шаблонов
приложений, мы рекомендуем использовать среду .NET Framework для большинства имеющихся
сценариев.
В большинстве случаев при таком сценарии перенос существующих приложений на .NET 5 не требуется.
Можно использовать контейнеры Docker, в которые включена традиционная платформа .NET Framework.
Тем не менее для расширения готовых приложений, например для разработки новой службы в ASP.NET
Core рекомендуется использовать .NET 5.
Кроме того, пакет обеспечения совместимости Windows расширяет доступную для .NET Standard 2.0
область API-интерфейсов в Windows. Этот пакет позволяет почти без изменений перекомпилировать
существующий код под платформу .NET Standard версии 2.x, чтобы выполнять его в Windows.
Несмотря на значительный прогресс, достигнутый после выхода .NET Standard 2.0 и .NET Core 2.1 и более
поздних версий, некоторые пакеты NuGet пока запускаются только в ОС Windows и не поддерживают
.NET Core и более поздних версий. Если эти пакеты имеют важное значение для вашего приложения,
необходимо использовать .NET Framework в контейнерах Windows.
Веб-формы ASP.NET. Эта технология доступна только в .NET Framework. В настоящее время
добавление веб-форм ASP.NET в среду .NET и более поздних версий не планируется.
Службы WCF. Даже с клиентской библиотекой WCF, которая позволяет использовать службы WCF
из среды .NET 5, по состоянию на январь 2021 г. реализация сервера WCF доступна только для .NET
Framework.
Службы, связанные с рабочим процессом. Службы Windows Workflow Foundation (WF), Workflow
Services (WCF и WF в одной службе) и WCF Data Services (известные как службы данных ADO.NET)
доступны только в среде .NET Framework. В настоящий момент не планируется их перенос в .NET 5.
Дополнительные ресурсы
Документация по .NET
https://docs.microsoft.com/dotnet/fundamentals
Перенос проектов в .NET 5
https://channel9.msdn.com/Events/dotnetConf/2020/Porting-Projects-to-NET-5
Инструкции по использованию .NET в Docker
https://docs.microsoft.com/dotnet/core/docker/introduction
Общие сведения о компонентах .NET
https://docs.microsoft.com/dotnet/standard/components
НА ЗА Д ВПЕРЕД
Таблица для принятия решений. Использование
платформ .NET для Docker
02.11.2021 • 2 minutes to read
В таблице ниже для принятия решений приводятся сводные сведения о том, когда следует использовать
.NET Framework или .NET 5. Помните, что для контейнеров Linux требуются узлы Docker на основе Linux
(виртуальные машины или серверы), а для контейнеров Windows — узлы Docker на основе Windows
Server (виртуальные машины или серверы).
IMPORTANT
На компьютерах разработки выполняется один узел Docker: Linux или Windows. Все связанные микрослужбы,
которые должны запускаться и тестироваться вместе в рамках одного решения, должны выполняться на одной
платформе контейнеров.
Службы SignalR .NET Core 2.1 или более поздней .NET Framework
версии .NET Core 2.1 или более поздней
версии
WCF, WF и другие устаревшие WCF в .NET Core (только клиентская .NET Framework
платформы библиотека) WCF в .NET 5 (только клиентская
библиотека)
АРХИТЕКТУРА И ТИП ПРИЛОЖЕНИЯ КОНТЕЙНЕРЫ L IN UX КОНТЕЙНЕРЫ W IN DO W S
НА ЗА Д ВПЕРЕД
Для какой ОС использовать контейнеры .NET
02.11.2021 • 2 minutes to read
Для Windows можно использовать Windows Server Core или Windows Nano Server. Эти версии Windows
предоставляют разные особенности (IIS в Windows Server Core или резидентный веб-сервер, такой как
Kestrel, в Nano Server), которые могут быть необходимы в .NET Framework или .NET 5 соответственно.
Для Linux доступно и поддерживается множество дистрибутивов в официальных образах Docker .NET
(например, Debian).
На рисунке 3-1 представлены возможные версии операционной системы в зависимости от используемой
платформы .NET.
При развертывании устаревших приложений .NET Framework выберите в качестве целевой ОС Windows
Server Core, которая совместима с устаревшими приложениями и службами IIS, но образ которой имеет
больший размер. При развертывании приложений .NET 5 в качестве целевой ОС можно выбрать Windows
Nano Server, которая оптимизирована для облака, использует Kestrel, имеет образ меньшого размера и
запускается быстрее. В качестве целевой среды можно выбрать ОС Linux, которая поддерживает Debian,
Alpine и другие дистрибутивы. Можете также использовать образ Kestrel, который имеет меньший размер
и запускается быстрее.
В том случае, если требуется использовать другой дистрибутив Linux или если нужен образ с версиями,
не предоставляемыми Майкрософт , можно также создать собственный образ Docker. Например, можно
создать образ с ASP.NET Core для работы на классической платформе .NET Framework и в Windows Server
Core, что для Docker является довольно редко используемым сценарием.
При добавлении имени образа в файл Dockerfile можно выбрать операционную систему и версию в
зависимости от используемого тега, как показано в следующих примерах:
ИЗОБРАЖЕНИЕ КОММЕНТАРИИ
НА ЗА Д ВПЕРЕД
Официальные .NET-образы Docker
02.11.2021 • 2 minutes to read
Официальные .NET-образы Docker — это образы Docker, оптимизированные Майкрософт. Они доступны
для всех в репозиториях Майкрософт в Центре Docker. Каждый репозиторий может содержать несколько
образов, в зависимости от версии платформы .NET и операционной системы (Linux Debian, Linux Alpine,
Windows Nano Server, Windows Server Core и т. д.).
Начиная с версии .NET Core 2.1, все образы .NET Core или более поздней версии, в том числе для ASP.NET
Core, можно найти в репозитории образов .NET на сайте Docker Hub: https://hub.docker.com/_/microsoft-
dotnet/.
Начиная с мая 2018 г., образы Майкрософт объединяются в реестре контейнеров Майкрософт .
Официальный каталог по-прежнему доступен только в центре Docker, и здесь можно найти обновленный
адрес для извлечения образа.
Почему так важен этот тип образа сборки? Этот образ не развертывается в рабочую среду. Это образ,
который вы используете для сборки содержимого, помещаемого в рабочий образ. Если вы используете
многоэтапную сборку Docker, этот образ будет применяться в среде непрерывной интеграции (CI) или в
среде сборки.
Производство
При производстве важно быстро развернуть и запустить контейнеры на основе рабочего образа .NET.
Поэтому образ только для среды выполнения на базе mcr.microsoft.com/dotnet/aspnet:5.0 имеет малый
размер и может быстро перемещаться по сети из реестра Docker к узлам Docker. Содержимое готово к
запуску, поэтому период времени от запуска контейнера до обработки результатов минимален. В модели
Docker не нужна компиляция кода C#, поскольку вы выполняете команду dotnet build или dotnet publish
при использовании контейнера сборки.
Хотя существует несколько версий образов .NET и ASP.NET Core, они все имеют один или несколько
общих уровней, включая базовый уровень. Поэтому образ занимает мало места на диске, ведь он
содержит лишь различия между вашим образом и базовым образом. В результате можно быстро
извлекать образы из реестра.
ОБРАЗ — КОММЕНТАРИИ
НА ЗА Д ВПЕРЕД
Проектирование архитектуры приложений на
основе контейнеров и микрослужб
02.11.2021 • 2 minutes to read
Корпоративные приложения могут быть сложными и часто состоят из нескольких служб, а не одной. В
таких случаях необходимо хорошо представлять себе другие подходы к проектированию архитектуры,
такие как использование микрослужб, а также определенные шаблоны проектирования на основе
доменов и принципы оркестрации контейнеров. Имейте в виду, что в этой главе описываются не только
микрослужбы в контейнерах, но и любые контейнерные приложения.
В случае сбоя процесса работа контейнера завершается и оркестратор принимает управление. Если в
оркестраторе настроена поддержка пяти выполняющихся экземпляров, то в случае сбоя одного из них
оркестратор создаст ему на замену еще один экземпляр контейнера. В пакетном задании процесс
запускается с параметрами. По завершении выполнения процесса работа считается выполненной. В этом
руководстве оркестраторы будут рассматриваться более подробно позже.
Возможны ситуации, когда в одном контейнере желательно выполнять несколько процессов. Так как
каждый контейнер может иметь только одну точку входа, в таком случае в контейнере можно
использовать скрипт , который будет запускать нужное количество программ. Например, можно
использовать Supervisor или аналогичное средство, отвечающее за запуск нескольких процессов в одном
контейнере. Но хотя архитектуры, предусматривающие выполнение несколько процессов в контейнере,
используются, это не очень популярное решение.
НА ЗА Д ВПЕРЕД
Контейнеризация монолитных приложений
02.11.2021 • 4 minutes to read
Вы можете создать одно монолитное веб-приложение или службу и развернуть их как контейнер. Само
приложение может не иметь монолитную внутреннюю структуру и состоять из нескольких библиотек,
компонентов или даже уровней (прикладной уровень, уровень домена, уровень доступа к данным и т. д.).
Но внешне оно будет представлять собой единый контейнер — единый процесс, единое веб-приложение
или единую службу.
Для управления этой моделью вы развертываете один контейнер, представляющий собой приложение.
Чтобы увеличить емкость, вы используете горизонтальное масштабирование, то есть просто добавляете
больше копий с подсистемой балансировки нагрузки спереди. Управлять одним развертыванием в одном
контейнере или виртуальной машине гораздо проще.
Вы можете включить в один контейнер несколько компонентов, библиотек или внутренних уровней, как
показано на рисунке 4-1. Монолитное контейнерное приложение содержит большую часть
функциональности в одном контейнере с внутренними слоями или библиотеками и горизонтально
масштабируется путем клонирования контейнера на нескольких серверах или виртуальных машинах.
Такой монолитный шаблон может конфликтовать с принципом контейнера: "контейнер выполняет одно
дело и в одном процессе", — но в некоторых случаях это не проблема.
Недостаток этого подхода становится очевидным, когда приложение разрастается и его необходимо
масштабировать. Если можно масштабировать приложение целиком, все получится. Но в большинстве
случаев необходимо масштабировать всего несколько частей приложения, пока другие компоненты
работают нормально.
Например, в типичном приложении для электронной коммерции, скорее всего, придется масштабировать
подсистему сведений о продуктах, поскольку клиенты чаще просматривают продукты, чем покупают.
Клиенты чаще складывают товары в корзину, чем оплачивают их. Не так много клиентов пишут
комментарии или просматривают историю покупок. И у вас может быть всего несколько сотрудников,
которые управляют содержимым и маркетинговыми кампаниями. При масштабировании монолитной
конструкции весь код для различных задач развертывается несколько раз и масштабируется в
одинаковой степени.
С точки зрения инфраструктуры, каждый сервер может выполнять множество приложений в одном узле
и применять допустимое соотношение эффективности использования ресурсов, как показано на рисунке
4-2.
Рис. 4-2 . Монолитная конструкция: узел выполняет несколько приложений, каждое приложение
выполняется как контейнер
В качестве среды контроля качества или ограниченной рабочей среды можно развертывать несколько
виртуальных машин с Docker и распределять нагрузку с помощью средства балансировки Azure, как
показано на рисунке 4-3. Так вы сможете управлять масштабированием, не используя крупные элементы,
поскольку все приложение размещено в одном контейнере.
Рис. 4-3 . Пример масштабирования приложения в одном контейнере с помощью нескольких узлов
Развертывание обновлений в виде образов Docker выполняется гораздо быстрее и эффективнее с точки
зрения использования сети. Образы Docker обычно запускаются за считанные секунды, что позволяет
ускорить выпуск. Остановить образ Docker можно с помощью команды docker stop , и обычно это
происходит моментально.
Docker имеет много плюсов для монолитных приложений, но это еще не полный список преимуществ.
Дополнительные возможности при управлении контейнерами открываются благодаря развертыванию с
помощью оркестраторов контейнеров, которые управляют различными экземплярами и жизненным
циклом каждого экземпляра контейнера. Когда вы разбиваете монолитное приложение на подсистемы,
которые затем можно масштабировать, разрабатывать и развертывать по отдельности, вы переходите на
уровень микрослужб.
Рис. 4-4 . Публикация приложения в одном контейнере в Службе приложений Azure из Visual Studio 2019
Если вам понадобятся другие возможности, платформы или зависимости, не поддерживаемые службой
приложений Azure, без Docker пришлось бы ждать, пока команда Azure обновит эти зависимости в
службе приложений. Или пришлось бы переключиться на другие службы, например Облачные службы
Azure, или даже виртуальные машины, где у вас было бы больше возможностей и можно было бы
установить необходимый компонент или платформу для приложения.
Благодаря поддержке контейнеров в Visual Studio 2017 и более поздних версий вы можете включать в
среду приложения любые компоненты, как показано на рисунке 4-4. Поскольку приложение выполняется
в контейнере, при добавлении зависимости можно включить ее в Dockerfile или образ Docker.
На рисунке 4-4 также показано, что поток публикации отправляет образ через реестр контейнеров. Это
может быть реестр контейнеров Azure (реестр, близкий к вашим развертываниям в Azure и защищенный
группами и учетными записями в Azure Active Directory) или другой реестр Docker, например центр Docker
или локальный реестр.
НА ЗА Д ВПЕРЕД
Управление состоянием и данными в
приложениях Docker
02.11.2021 • 4 minutes to read
Представьте себе контейнер как экземпляр процесса. Процесс не находится в неизменном состоянии. И
хотя контейнер может записывать данные в локальное хранилище, предполагать, что экземпляр всегда
будет на месте — это все равно, что надеяться на постоянство одной ячейки памяти. Вы должны
предполагать, что образы контейнеров, как и процессы, имеют несколько экземпляров или конечном
итоге будут удалены. Если для управления ими используется оркестратор контейнеров, следует
предполагать, что они могут перемещаться из одного узла (или виртуальной машины) в другой.
Тома хранятся в той части файловой системы узла, которая находится под управлением Docker.
Подключения привязок можно сопоставить с любой папкой в файловой системе узла, поэтому
доступом нельзя управлять из процесса Docker, что может представлять угрозу для безопасности,
поскольку контейнер может получить доступ к конфиденциальным папкам операционной
системы.
Из удаленного хранилища:
Удаленные реляционные базы данных, например базы данных SQL Azure или базы данных NoSQL,
такие как Azure Cosmos DB, или службы кэша, такие как Redis.
Из контейнера Docker:
Оверлейная файловая система . Эта функция Docker выполняет копирование при записи, при
котором обновленная информация сохраняется в корневой файловой системе контейнера. Эта
информация "накладывается" на изначальный образ, на котором базируется контейнер. Если удалить
контейнер из системы, эти изменения будут утеряны. Поэтому, хоть и возможно сохранить состояние
контейнера в его локальном хранилище, создание системы по такой модели будет противоречить
конструкции контейнера, состояние которого по умолчанию не отслеживается.
Тем не менее сейчас тома Docker являются предпочтительным способом обработки локальных данных в
Docker. Если вам требуются дополнительные сведения о хранении в контейнерах, ознакомьтесь с
разделами Docker storage drivers (Драйверы хранилища Docker) и About storage drivers (Основные
сведения о драйверах хранилища).
Тома — это каталоги из ОС узла, сопоставленные с каталогами в контейнерах. Если код в контейнере
имеет доступ к каталогу, на самом деле он обращается к каталогу на ОС узла. Этот каталог не привязан к
времени существования самого контейнера, находится под управлением Docker и изолирован от
основных функциональных возможностей хост -компьютера. Поэтому тома данных хранят данные
независимо от контейнера. Если удалить контейнер или образ из узла Docker, данные из томов данных не
будут удалены.
Тома могут быть именованными или анонимными (по умолчанию). Именованные тома — это следующий
этап развития контейнеров томов данных. Они упрощают обмен данными между контейнерами.
Тома также поддерживают драйверы томов, позволяющие хранить данные на удаленных узлах и т. д.
Подключения привязки доступны довольно давно и позволяют сопоставлять любую папку с точкой
подключения в контейнере. Подключения привязки имеют больше ограничений, чем тома, и с ними
связаны некоторые проблемы безопасности, поэтому тома являются рекомендуемым способом.
Подключения tmpfs по сути являются виртуальными папками, которые существуют только в памяти
узла и никогда не записываются в файловую систему. Они быстрые и безопасные, но используют ресурсы
памяти и предназначены только для временных несохраняемых данных.
Как показано на рисунке 4-5, обычные тома Docker могут храниться за пределами самих контейнерами,
но в физических границах сервера узла или виртуальной машины. Тем не менее контейнеры Docker с
одного сервера узла или виртуальной машины не могут обращаться к тому на другом сервере узла или
виртуальной машине. Другими словами, с помощью этих томов невозможно управлять данными
контейнеров, которые выполняются на разных узлах Docker, хотя такой режим работы можно
реализовать с помощью драйвера томов, который поддерживает удаленные узлы.
Рис. 4-5 . Тома и внешние источники данных для приложений на основе контейнера
Тома могут совместно использоваться несколькими контейнерами, но только на одном узле, если вы не
используете удаленный драйвер с поддержкой удаленных узлов. Кроме того, когда контейнеры Docker
управляются оркестратором, контейнеры могут "перемещаться" между узлами в рамках оптимизации,
выполняемой кластером. Поэтому тома данных не рекомендуется использовать для бизнес-данных. Но
это хороший инструмент для работы с файлами трассировки, временными файлами или подобными
элементами, которые не влияют на целостность бизнес-данных.
Удаленные источники данных и инструменты кэширования, такие как база данных Azure SQL,
Azure Cosmos DB или служба кэша, например Redis, можно использовать в упакованных в контейнеры
приложениях так же, как они используются при разработке без контейнеров. Это проверенный способ
хранения данных бизнес-приложений.
Служба хранилища Azure Бизнес-данные, как правило, необходимо хранить во внешних ресурсах или
базах данных, например в службе хранилища Azure. Служба хранилища Azure предоставляет следующие
службы в облаке:
Реляционные базы данных и базы данных NoSQL. Существует множество вариантов внешних баз
данных — от реляционных, таких как SQL Server, PostgreSQL и Oracle, до баз данных NoSQL, например
Azure Cosmos DB, MongoDB и т д. Такие базы являются отдельной темой и не рассматриваются в этом
руководстве.
НА ЗА Д ВПЕРЕД
Сервисноориентированная архитектура
02.11.2021 • 2 minutes to read
Теперь эти службы можно развернуть как контейнеры Docker, которые помогают решать проблемы
развертывания, так как в образ контейнера включены все зависимости. Однако, если вы используете
отдельные узлы Docker, то при необходимости масштабирования приложений SOA вы столкнетесь с
проблемами масштабируемости и доступности. Именно для решения таких проблем предназначено
программное обеспечение для кластеризации Docker, или оркестратор, которое описано в следующих
разделах, где мы расскажем о способах развертывания микрослужб.
Контейнеры Docker являются полезным (но необязательным) элементом как для традиционных
архитектур, ориентированных на службы, так и более сложных архитектур с микрослужбами.
Это руководство посвящено описанию микрослужб, поскольку подход SOA менее требователен по
сравнению с требованиями и техниками архитектуры микрослужб. Если вы знаете, как создать
приложение на основе технологии микрослужб, то вы сможете создать и простое
сервисноориентированное приложение.
НА ЗА Д ВПЕРЕД
Архитектура микрослужб
02.11.2021 • 2 minutes to read
Само название предполагает , что архитектура микрослужб является подходом к созданию серверного
приложения как набора малых служб, Это означает , что архитектура микрослужб главным образом
ориентирована на серверную часть, несмотря на то, что этот подход также используется для внешнего
интерфейса. где каждая служба выполняется в своем процессе и взаимодействует с остальными
службами по таким протоколам, как HTTP/HTTPS, WebSockets или AMQP. Каждая микрослужба реализует
специфические возможности в предметной области и свою бизнес-логику в рамках определенного
ограниченного контекста, должна разрабатываться автономно и развертываться независимо. Наконец, у
каждой микрослужбы должны быть соответствующие собственные модель данных и логика предметной
области (владение и децентрализованное управление данными); для каждой микрослужбы могут
применяться разные технологии хранилищ (SQL, NoSQL) и разные языки программирования.
Каково размера должна быть микрослужба? При разработке микрослужбы размер не должен быть
важным фактором. Главным должно быть создание слабо связанных служб, что позволяет добавиться
автономности при разработке, развертывании и масштабировании каждой службы. Конечно же, при
определении и проектировании микрослужб следует стремиться к тому, чтобы они были как можно
меньше, если только они не имеют слишком много прямых зависимостей от других микрослужб.
Внутренняя связанность микрослужбы и ее независимость от других служб важнее ее размера.
Почему следует использовать архитектуру микрослужб? Если говорить кратко, то это гибкость в
долгосрочной перспективе. Микрослужбы обеспечивают превосходные возможности сопровождения в
крупных комплексных системах с высокой масштабируемостью за счет создания приложений,
основанных на множестве независимо развертываемых служб с автономными жизненными циклами.
Как показано на рис. 4-6, в традиционном монолитном подходе приложение масштабируется путем
клонирования всего приложения на несколько серверов или виртуальных машин. В подходе с
использованием микрослужб функциональные возможности изолируются в небольших службах, и
каждую службу можно масштабировать независимо от других. Подход на основе микрослужб нацелен на
гибкость изменений и ускорение последовательных улучшений каждой микрослужбы, так как вы
получаете возможность изменять небольшие части крупных, комплексных и масштабируемых
приложений.
Ниже перечислены важные аспекты успешного ввода системы на основе микрослужб в эксплуатацию:
Из этих аспектов только первые три рассматриваются в данном руководстве. Последние два, связанные с
жизненным циклом приложения, описываются в дополнительной электронной книге Жизненный цикл
контейнерного приложения Docker на основе платформы и средств Майкрософт .
Дополнительные ресурсы
Марк Руссинович (Mark Russinovich). Микрослужбы: революция в сфере приложений,
движимая облачными технологиями
https://azure.microsoft.com/blog/microservices-an-application-revolution-powered-by-the-cloud/
Мартин Фоулер (Mar tin Fowler). Микрослужбы
https://www.martinfowler.com/articles/microservices.html
Мартин Фоулер (Mar tin Fowler). Требования для микрослужб
https://martinfowler.com/bliki/MicroservicePrerequisites.html
Джимми Нилссон (Jimmy Nilsson). Фрагментирование облачных вычислений
https://www.infoq.com/articles/CCC-Jimmy-Nilsson
Сезар де ла Торре (Cesar de la Torre). Жизненный цикл контейнерного приложения
Docker на основе платформы и средств Майкрософт (электронная книга, доступная для
скачивания) https://aka.ms/dockerlifecycleebook
НА ЗА Д ВПЕРЕД
Владение данными в каждой микрослужбе
02.11.2021 • 4 minutes to read
Важное правило архитектуры микрослужб состоит в том, что каждая микрослужба должна быть
владельцем своих данных и логики предметной области. Так же как полнофункциональное приложение
является владельцем своих логики и данных, так и каждая микрослужба должна быть владельцем своей
логики и данных в рамках автономного жизненного цикла, причем развертывание производится
независимо для каждой микрослужбы.
Это означает , что концептуальная модель предметной области будет различаться для разных подсистем
и микрослужб. Для примера можно взять корпоративное приложение, в котором каждая из подсистем
управления отношениями с клиентами (CRM), финансовых транзакций и поддержки клиентов
обращается к уникальным атрибутам и данным сущностей и использует собственный ограниченный
контекст.
С другой стороны, традиционный подход (на основе единых данных), применяемый во многих
приложениях, предполагает наличие одной централизованной базы данных или небольшого количества
баз данных. Часто это нормализованная база данных SQL, которая используется для всего приложения и
всех его внутренних подсистем, как показано на рис. 4-7.
В традиционном подходе имеется отдельная база данных, совместно используемая всеми службами, как
правило, в многоуровневой архитектуре. В подходе с использованием микрослужб каждая микрослужба
владеет собственной моделью или данными. Подход на основе централизованной базы данных
изначально выглядит более простым и позволяющим повторно использовать сущности в разных
подсистемах для обеспечения согласованности. Но в действительности вы в итоге получаете огромные
таблицы, обслуживающие множество разных подсистем и содержащие атрибуты и столбцы, которые в
большинстве случаев не нужны. Это все равно что пытаться использовать одну и ту же карту для
небольшого пешего похода, суточной поездки на автомобиле и изучения географии.
Монолитное приложение, обычно с одной реляционной базой данных, имеет два важных преимущества:
транзакции, обладающие свойствами атомарности, согласованности, изолированности и долговечности,
и язык SQL. Оба этих преимущества распространяются на все таблицы и данные, связанные с
приложением. Такой подход позволяет легко писать запросы, объединяющие данные из нескольких
таблиц.
Но при переходе на архитектуру микрослужб получать доступ к данным становится сложнее. Даже при
использовании транзакций ACID в микрослужбах или ограниченном контексте важно учитывать, что
данные, принадлежащие каждой микрослужбе, являются частными для этой микрослужбы и должны
быть доступны только синхронно через соответствующие конечные точки API (gRPC, SOAP и т. д.) или
асинхронно через систему обмена сообщениями (AMQP и т. д.).
Инкапсуляция данных делает микрослужбы слабосвязанными, благодаря чему они могут изменяться
независимо друг от друга. Если бы несколько служб обращались к одним и тем же данным, изменения
схемы требовали бы согласованного изменения всех служб. При этом автономность жизненного цикла
микрослужб нарушалась бы. Однако распределенные структуры данных означают невозможность
выполнения транзакции, обладающей свойствами атомарности, согласованности, изолированности и
долговечности, в рамках нескольких микрослужб. Из этого, в свою очередь, следует , что если бизнес-
процесс охватывает несколько микрослужб, необходимо обеспечивать итоговую согласованность. Это
гораздо сложнее в реализации, чем простые соединения SQL, поскольку невозможно создать
ограничения целостности или использовать распределенные транзакции между отдельными базами
данных, как мы объясним позднее. Аналогичным образом многие другие возможности реляционных баз
данных недоступны в рамках нескольких микрослужб.
Если разбираться дальше, микрослужбы часто используют базы данных разных типов. Современные
приложения хранят и обрабатывают разнообразные типы данных, и реляционная база данных — не
всегда лучший выбор. В некоторых ситуациях база данных NoSQL, например Azure CosmosDB или
MongoDB, может иметь более удобную модель данных и обеспечивать более высокую
производительность и масштабируемость по сравнению с базой данных SQL, например SQL Server или
базой данных SQL Azure. В других случаях реляционная база данных по-прежнему является оптимальным
решением. По этой причине в приложениях на основе микрослужб часто используется сочетание баз
данных SQL и NoSQL. Такой подход иногда называют разнородным хранением данных.
Таким образом, микрослужба похожа на ограниченный контекст , но она также определена как
распределенная служба. Она создается как отдельный процесс для каждого ограниченного контекста и
должна использовать упомянутые ранее распределенные протоколы, такие как HTTP/HTTPS, WebSockets
или AMQP. В свою очередь, шаблон ограниченного контекста не указывает , является ли ограниченный
контекст распределенной службой или просто логической границей (например, подсистемой общего
назначения) в пределах монолитного приложения.
Важно отметить, что сначала желательно определить службу для каждого ограниченного контекста.
Однако проектирование необязательно ограничивать этим. Иногда следует спроектировать
ограниченный контекст или бизнес-микрослужбу, которые состоят из нескольких физических служб. Но,
в конечном счете, оба шаблона (ограниченный контекст и микрослужба) тесно связны друг с другом.
Дополнительные ресурсы
Крис Ричардсон (Chris Richardson). Шаблон: база данных для каждой службы
https://microservices.io/patterns/data/database-per-service.html
Мартин Фоулер (Mar tin Fowler). BoundedContext
https://martinfowler.com/bliki/BoundedContext.html
Мартин Фоулер (Mar tin Fowler). PolyglotPersistence
https://martinfowler.com/bliki/PolyglotPersistence.html
Альберто Брандолини (Alber to Brandolini). Стратегическое предметно-
ориентированное проектирование с сопоставлением контекста
https://www.infoq.com/articles/ddd-contextmapping
НА ЗА Д ВПЕРЕД
Логическая и физическая архитектура
02.11.2021 • 2 minutes to read
Теперь будет полезно отвлечься и обсудить разницу между логической и физической архитектурами, а
также поговорить о том, какое значение она имеет для проектирования приложений на основе
микрослужб.
Начнем с того, что для разработки микрослужб не требуется использовать какую-либо определенную
технологию. Например, для создания архитектуры на основе микрослужб контейнеры Docker не
являются обязательными. Микрослужбы могут также выполняться как обычные процессы. Микрослужбы
образуют логическую архитектуру.
Кроме того, даже несмотря на то, что микрослужба может быть физически реализована как отдельная
служба, процесс или контейнер (для простоты именно такой подход был выбран в первоначальной
версии приложения eShopOnContainers), подобное соответствие бизнес-микрослужбы и физической
службы или контейнера не всегда является обязательным, особенно при разработке больших и сложных
приложений, состоящих из десятков и даже сотен служб.
Возможно, вы уже выделили определенные микрослужбы или ограниченные контексты, но это не значит ,
что оптимальный способ их реализации всегда состоит в создании отдельной службы (например, веб-API
ASP.NET) или отдельного контейнера Docker для каждой микрослужбы. Правило, гласящее, что каждая
микрослужба должна реализовываться как отдельная служба или контейнер, является слишком строгим.
Как показано на рис. 4-8, микрослужба каталога может состоять из нескольких служб или процессов. Это
может быть несколько служб на основе веб-интерфейсов API ASP.NET или любых других служб,
использующих протокол HTTP либо иной протокол. Более того, эти службы могут использовать одни и
те же данные при условии, что они связаны с одной предметной областью.
Службы в примере имеют общую модель данных, так как служба на основе веб-интерфейса API
обращается к тем же данным, что и служба поиска. Поэтому в физической реализации микрослужбы вы
разделяете эту функциональность, чтобы каждую из внутренних служб можно было масштабировать по
мере необходимости. Например, для службы на основе веб-интерфейса API обычно может требоваться
больше экземпляров, чем для службы поиска, или наоборот.
НА ЗА Д ВПЕРЕД
Распределенное управление данными: проблемы
и решения
02.11.2021 • 8 minutes to read
Как вы определяете границы между контекстами приложения с отдельной предметной областью для
каждого контекста, так же вы определяете границы каждой микрослужбы, ее модель предметной
области и данные. Всегда старайтесь свести к минимуму взаимозависимость между этими
микрослужбами. Далее в главе Определение границ модели предметной области для каждой
микрослужбы будет подробно рассматриваться это разграничение и проектирование модели
предметной области.
Шлюз API . Для простого объединения данных из нескольких микрослужб с разными базами данных
рекомендуется использовать микрослужбу агрегирования — шлюз API. Будьте осторожны при
применении этого шаблона, поскольку он может стать слабым местом вашей системы и нарушить
принцип автономности микрослужб. Чтобы смягчить негативные последствия, используйте несколько
мелких шлюзов API для различных вертикальных срезов или областей системы. Шаблон шлюза API более
подробно описан в разделе Использование шлюза API ниже.
CQRS с таблицами запросов/ чтения. Еще одно решение для объединения данных из нескольких
микрослужб — шаблон материализованного представления. При таком подходе вы заранее создаете
(готовите денормализованные данные до фактической отправки запросов) таблицу, доступную только
для чтения, с данными, принадлежащими нескольким микрослужбам. Таблица имеет формат ,
соответствующий потребностям клиентского приложения.
Представьте себе экран мобильного приложения. Если у вас одна база данных, вы можете собрать
данные для этого экрана с помощью SQL-запроса, выполняющего сложное соединение с использованием
нескольких таблиц. Но если у вас несколько баз данных и каждая база данных принадлежит отдельной
микрослужбе, невозможно отправить в них запрос и создать соединение SQL. Такой сложный запрос
становится проблемой. Эту проблему можно решить с помощью подхода CQRS — создайте
денормализованную таблицу в другой базе данных, которая используется только для запросов. Таблица
может предназначаться специально для данных, необходимых в этом сложном запросе, и между полями,
необходимыми для экрана приложения, и столбцами в таблице запроса может существовать отношение
один к одному. Такой метод также можно использовать для составления отчетов.
Этот подход позволяет не только решить изначальную проблему (как отправлять запросы в несколько
микрослужб), но и значительно повысить производительность по сравнению с использованием сложных
соединений, поскольку у вас уже есть все необходимые приложению данные в таблице запроса. Конечно,
если вы используете принцип разделения ответственности на команды и запросы (Command and Query
Responsibility Segregation, CQRS) с таблицами запросов/чтения, придется проделать дополнительную
работу и проследить за итоговой согласованностью. Тем не менее мы рекомендуем применять принцип
CQRS с несколькими базами данных там, где существуют особые требования к производительности и
масштабируемости в ситуации совместной работы (или соперничества, это как посмотреть).
" Холодные данные " в центральных базах данных. Для составления сложных отчетов и
выполнения запросов, не требующих немедленного ответа, рекомендуется экспортировать "горячие
данные" (данные о транзакциях из микрослужб) как "холодные данные" в большие базы данных,
использующиеся только для отчетности. Система центральной базы данных может основываться на
больших данных, например Hadoop, представлять собой хранилище данных, например на базе
хранилища данных Azure SQL, или являться просто базой данных SQL, использующейся только для
отчетов (если размер не имеет значения).
Имейте в виду, что эта централизованная база данных будет использоваться только для запросов и
отчетов, которым не требуются данные в режиме реального времени. Исходные обновления и
транзакции в качестве источника истины должны храниться в данных микрослужб. Синхронизируйте
данные при наступлении событий (как описано в следующих разделах) или через инструменты импорта и
экспорта инфраструктуры другой базы данных. Если вы используете управление событиями, процесс
интеграции будет схож с методом распространения данных, описанным в разделе о таблицах запросов
по принципу CQRS.
В гипотетической монолитной версии этого приложения при изменении цены в таблице "Товары"
подсистема каталога может просто использовать транзакцию ACID, чтобы обновить текущую цену в
таблице "Корзина".
Микрослужба каталога не должна напрямую изменять таблицу "Корзина", поскольку эта таблица
принадлежит микрослужбе корзины. Чтобы обновить сведения в микрослужбе корзины, микрослужба
каталога может использовать только итоговую согласованность, возможно на основе асинхронной связи,
например событий интеграции (взаимодействие на основе сообщений и событий). Вот как такая итоговая
согласованность микрослужб выполняется в примере приложения eShopOnContainers.
Как гласит теорема CAP, вы должны выбирать между доступностью и согласованностью данных по
принципу ACID. В большинстве случаев при использовании микрослужб доступность и масштабируемость
имеют приоритет над строгой согласованностью. Критически важные приложения должны непрерывно
работать, и разработчики могут решить проблему строгой согласованности, используя методы работы со
слабой или итоговой согласованностью. Такой подход используется в большинстве архитектур на базе
микрослужб.
Кроме того, транзакции в стиле ACID или с двухфазной фиксацией не просто противоречат принципам
микрослужб — большинство баз данных NoSQL (например, Azure Cosmos DB, MongoDB и т. д.) не
поддерживают транзакции с двухфазной фиксацией, типичные для сценариев распространенных баз
данных. Согласованность данных в разных службах и базах данных все же имеет большое значение. Эта
проблема также связана с вопросом распространения изменений в нескольких микрослужбах, когда
некоторые данные должны быть избыточными — например, когда название или описание товара
должно присутствовать в микрослужбе каталога и в микрослужбе корзины.
Хорошим решением этой проблемы может стать использование итоговой согласованности между
микрослужбами, выраженной в управляемом событиями взаимодействии и системе публикации и
подписки. Эти темы обсуждаются в разделе Асинхронное взаимодействие, управляемое событиями.
Чаще всего используются службы на базе HTTP (REST), поскольку они очень простые. Использовать HTTP
можно. Но как именно? Если вы используете запросы и ответы HTTP только для взаимодействия между
микрослужбами и клиентскими приложениями или шлюзами API, это нормально. Но если вы создаете
длинные цепочки синхронных HTTP-вызовов для взаимодействия через границы микрослужб, как если бы
микрослужбы были объектами в монолитном приложении, в конце концов в приложении возникнут
проблемы.
Представьте, что клиентское приложение делает вызов HTTP API к отдельной микрослужбе, например
микрослужбе заказов. Если микрослужба заказов, в свою очередь, вызывает дополнительные
микрослужбы по протоколу HTTP в рамках одного цикла запросов и ответов, вы создадите цепочку HTTP-
вызовов. Поначалу это может казаться разумным. Но при таком подходе следует учитывать несколько
важных аспектов:
Если внутренние микрослужбы взаимодействуют с помощью цепочек HTTP-запросов, как описано выше,
такое приложение можно назвать монолитным, но основанным на протоколе HTTP, а не на механизмах
внутреннего взаимодействия процессов.
Поэтому, чтобы повысить автономность и устойчивость микрослужб, следует как можно реже
использовать цепочки запросов и ответов для взаимодействия между микрослужбами. Рекомендуется
использовать только асинхронное взаимодействие для связи между микрослужбами — асинхронное
взаимодействие, управляемое сообщениями и событиями, или (асинхронные) HTTP-опросы независимо от
изначального цикла HTTP-запросов и ответов.
Дополнительные ресурсы
Теорема CAP
https://en.wikipedia.org/wiki/CAP_theorem
Итоговая согласованность
https://en.wikipedia.org/wiki/Eventual_consistency
Основные сведения о согласованности данных
https://docs.microsoft.com/previous-versions/msp-n-p/dn589800(v=pandp.10)
Мартин Фоулер (Mar tin Fowler). CQRS ( разделение обязанностей запросов и команд )
https://martinfowler.com/bliki/CQRS.html
Материализованное представление
https://docs.microsoft.com/azure/architecture/patterns/materialized-view
Чарльз Роу (Charles Row). ACID и BASE: изменение pH- показателя обработки
транзакций в базах данных
https://www.dataversity.net/acid-vs-base-the-shifting-ph-of-database-transaction-processing/
Компенсирующие транзакции
https://docs.microsoft.com/azure/architecture/patterns/compensating-transaction
Уди Дахан (Udi Dahan). Объединение на основе служб
https://udidahan.com/2014/07/30/service-oriented-composition-with-video/
НА ЗА Д ВПЕРЕД
Определение границ модели предметной
области для каждой микрослужбы
02.11.2021 • 5 minutes to read
Границы и размеры модели для каждой микрослужбы необходимо определять не в целях мельчайшего
разделения, хотя следует стремиться к минимальному размеру микрослужб. Ваша цель — логичное
разделение на основе ваших знаний о предметной области. Главное не размер, а функционал. Кроме
того, если для определенной области приложения требуется особая слаженность в связи с большим
количеством зависимостей, это также указывает на необходимость создания отдельной микрослужбы.
Слаженность позволяет понять, как разделять или объединять микрослужбы. Постепенно изучая
предметную область, вы будете снова и снова менять размер микрослужб. Подбор правильного
размера — это длительный процесс.
Кроме того, при выборе структуры вам следует руководствоваться законом Конвея, который гласит , что
приложение отражает социальные границы организации, создавшей его. Но иногда верно обратное —
программное обеспечение формирует структуру организации. Попробуйте использовать закон Конвея в
противоположную сторону и построить границы в соответствии со своими идеальными
представлениями о компании, стараясь оптимизировать бизнес-процессы.
Для определения ограниченных контекстов можно использовать шаблон DDD под названием Шаблон
сопоставления контекстов. Сопоставляя контексты, вы определяете различные контексты в приложении
и их границы. Как правило, существуют различные контексты и границы для каждой небольшой
подсистемы. При сопоставлении контекстов становятся очевидными границы между предметными
областями. Ограниченный контекст автономен и включает в себя элементы только одной предметной
области, например сущности, а также определяет схему интеграции с другими ограниченными
контекстами. Этим он похож на микрослужбу: она автономна, реализует определенные возможности
предметной области и обеспечивает интерфейсы. Поэтому сопоставление контекстов и ограниченные
контексты помогают определить границы модели предметной области для ваших микрослужб.
При разработке крупного приложения вы увидите, как можно разделить его предметную область.
Например, специалист по области каталога будет называть сущности в каталоге не так, как специалист
по области доставки. Или сущность предметной области пользователя может отличаться по размеру и
количеству атрибутов у специалиста по взаимодействию с клиентами, который хочет хранить все
сведения о клиенте, и у специалиста по заказам, которому нужны лишь некоторые данные о клиенте.
Очень трудно устранить неоднозначность всех терминов предметной области во всех областях в
крупном приложении. Но суть в том, что вам и не следует унифицировать термины. Просто примите
различия и многообразие каждой предметной области. Если вы попытаетесь создать единую базу
данных для всего приложения, это будет непросто, и унифицированный словарь не устроит
специалистов по разным областям. Поэтому ограниченные контексты (реализованные как микрослужбы)
помогут понять, где можно использовать термины определенной предметной области и где следует
разделить систему и создать дополнительные ограниченные контексты с другими предметными
областями.
Вы поймете, что правильно выбрали границы и размеры всех ограниченных контекстов и моделей
предметной области, если между этими моделями будет существовать несколько прочных связей, и вам
не обязательно объединять информацию из нескольких моделей предметной области при выполнении
типичных операций в приложении.
При выборе размера модели предметной области для каждой микрослужбы руководствуйтесь
следующим принципом: у вас должен быть автономный и максимально изолированный ограниченный
контекст , с которым можно работать без постоянного обращения к другим контекстам (другим моделям
микрослужб). На рис. 4-10 показано, как несколько микрослужб (несколько ограниченных контекстов)
могут иметь собственную модель и как их сущности могут быть определены в зависимости от
конкретных требований для каждой предметной области в вашем приложении.
На рисунке 4-10 показан пример сценария, относящийся к системе управления сетевыми конференциями.
Та же сущность отображается как "Пользователи", "Покупатели", "Плательщики" и "Клиенты" в
зависимости от ограниченного контекста. Вы определяете несколько ограниченных контекстов, которые
можно реализовать как микрослужбы, опираясь на предметные области, выбранные специалистами по
этим областям. Как видите, некоторые сущности представлены только в одной модели микрослужбы,
например "Платежи" в микрослужбе оплаты. Это будет легко реализовать.
Но некоторые сущности могут иметь разные формы и один идентификатор в различных моделях
предметных областей в различных микрослужбах. Например, сущность "Пользователь" определена в
микрослужбе управления конференциями. Тот же пользователь и с тем же идентификатором называется
"Покупатель" в микрослужбе заказов, "Плательщик" в микрослужбе платежей и "Клиент " в микрослужбе
клиентской службы. Дело в том, что каждый специалист в предметной области использует единый язык,
по-своему воспринимает пользователя и приписывает ему разные атрибуты. Сущность пользователя в
модели микрослужбы для управления конференциями содержит его персональные данные. Но эти
атрибуты могут не понадобиться этому же пользователю в роли плательщика в микрослужбе оплаты
или в роли клиента в микрослужбе клиентской службы.
При декомпозиции традиционной модели данных между ограниченными контекстами у вас может быть
несколько сущностей, которые совместно используют одно удостоверение (покупатель также является
пользователем), с различными атрибутами в каждом ограниченном контексте. Вы видите, что
пользователь присутствует в модели микрослужбы для управления конференциями в виде сущности
"Пользователь". А в микрослужбе ценообразования он представлен как сущность "Покупатель" и имеет
другие атрибуты и данные. Отдельным микрослужбам или ограниченным контекстам не нужны все
данные сущности "Пользователь", только их часть, в зависимости от актуальной проблемы или
контекста. Например, в модели микрослужбы ценообразования не нужен адрес или имя пользователя,
только идентификатор и статус для определения скидки при назначении цены за место для покупателя.
Сущность "Рабочее место" имеет одно название, но разные атрибуты в каждой модели предметной
области. Однако у сущности "Рабочее место" везде одинаковый идентификатор, как у "Пользователя" и
"Покупателя".
По сути, существует общее понятие пользователя в различных службах (предметных областях), где он
имеет один и тот же идентификатор. Но в каждой модели предметной области указаны разные сведения
о сущности пользователя. Поэтому нужен способ сопоставления сущности пользователя в разных
предметных областях (или микрослужбах).
НА ЗА Д ВПЕРЕД
Сравнение шаблона шлюза API с прямым
взаимодействием клиента и микрослужбы
02.11.2021 • 13 minutes to read
При таком подходе у каждой микрослужбы есть общедоступная конечная точка, иногда с отдельным
портом TCP для каждой микрослужбы. Например, определенная служба может иметь следующий URL-
адрес в Azure:
http://eshoponcontainers.westus.cloudapp.azure.com:88/
В рабочей среде на основе кластера этот URL-адрес будет указывать на подсистему балансировки
нагрузки кластера, которая, в свою очередь, распределяет запросы между микрослужбами. В
производственной среде можно использовать контроллер доставки приложений, например шлюз
приложения Azure между вашими микрослужбами и Интернетом. Данный слой выступает как
прозрачный уровень, который не только выполняет балансировку нагрузки, но и защищает службы
благодаря завершению SSL-запросов. Это уменьшает нагрузку на узлах за счет разгрузки завершения
SSL-запросов и других задач, активно использующих ЦП, в шлюз приложений Azure. В любом случае
подсистема балансировки нагрузки и контроллер доставки приложений прозрачны с точки зрения
логической архитектуры приложения.
Архитектура прямого взаимодействия клиента и микрослужбы достаточно хорошо подходит для
небольших приложений на основе микрослужб, особенно если клиентское приложение представляет
собой веб-приложение на стороне сервера, например приложение MVC ASP.NET. Однако при создании
больших и сложных приложений на основе микрослужб (например, при обработке десятков типов
микрослужб) и особенно в том случае, если клиентские приложения представляют собой удаленные
мобильные приложения или одностраничные веб-приложения, этот подход приводит к появлению
нескольких проблем.
Как клиентские приложения могут свести к минимуму число запросов к серверной части и уменьшить
частоту обмена данными с несколькими микрослужбами?
API нескольких микрослужб может быть не слишком хорошо приспособлено для удовлетворения
потребностей различных клиентских приложений. Например, потребности мобильного приложения
могут отличаться от потребностей веб-приложения. Для мобильных приложений может потребоваться
дополнительная оптимизация, чтобы повысить эффективность данных ответов. Это можно сделать,
агрегировав данные из нескольких микрослужб и возвращая один набор данных. Также иногда можно
исключить из ответа все данные, которые не требуются мобильному приложению. И, конечно же, эти
данные можно сжать. Опять же, можно предусмотреть удобный интерфейс или API между
микрослужбами и мобильным приложением для этого сценария.
Это означает , что промежуточный слой или уровень для косвенного обращения (шлюз) будет полезен в
приложениях на основе микрослужб. Если у вас нет шлюзов API, клиентские приложения должны
отправлять запросы непосредственно к микрослужбам, что может вызывать описанные ниже проблемы.
Проблемы безопасности. Без шлюза все микрослужбы будут доступны извне, что значительно
увеличивает уязвимую зону, если не скрыть внутренние микрослужбы, не используемые
клиентскими приложениями напрямую. Чем меньше уязвимая зона, тем надежнее будет ваше
приложение.
На рисунке 4-13 показано, как пользовательский шлюз API можно использовать в упрощенной
архитектуре на основе микрослужб, которая включает всего несколько микрослужб.
Рис. 4-13 . Использование шлюза API, реализованного в виде пользовательской службы
Приложения подключаются к одной конечной точке — шлюзу API, который настроен для пересылки
запросов в отдельные микрослужбы. В этом примере шлюз API будет реализован в виде
пользовательской службы ASP.NET Core WebHost, запущенной в виде контейнера.
Важно отметить, что на этой схеме вы использовали бы одну пользовательскую службу шлюза API,
взаимодействующую с несколькими и различными клиентскими приложениями. Этот факт может
привести к заметному риску, так как служба шлюза API будет расти и развиваться на основе множества
различных требований от клиентских приложений. Со временем служба шлюза API раздуется из-за этих
различных требований и по сути окажется подобной монолитному приложению или монолитной
службе. Поэтому настоятельно рекомендуется разделять шлюз API между различными службами или
между более мелкими шлюзами API, например по одному шлюзу для каждого типа форм-фактора
клиентского приложения.
Следует соблюдать осторожность при реализации шаблона шлюза API. Обычно не рекомендуется иметь
один шлюз API, который агрегирует все внутренние микрослужбы вашего приложения. Такой шлюз
выступает в качестве монолитного агрегатора или оркестратора и нарушает автономность микрослужб,
связывая все микрослужбы друг с другом.
При разделении уровня шлюза API на несколько шлюзов API, если приложение включает несколько
клиентских приложений, это разделение можно использовать в качестве основы для описания типов
шлюзов API, то есть разработать индивидуальный фасад для каждого клиентского приложения. Такую
схему иногда называют "Серверная часть для клиентской части" (BFF). Каждый шлюз API может
предоставлять различные API с учетом каждого типа клиентского приложения (а возможно, и форм-
фактора), на основе реализации кода адаптера, который вызывает несколько внутренних микрослужб,
как показано ниже.
Рис. 4-13.1. Использование нескольких пользовательских шлюзов API
На рис. 4-13.1 показаны шлюзы API, разделенные по типу клиента: для мобильных клиентов и для веб-
клиентов. Традиционное веб-приложение подключается к микрослужбе MVC, использующей шлюз веб-
API. В примере показана упрощенная архитектура с несколькими детально настроенными шлюзами API. В
этом примере границы для разделения шлюзов API строго основаны на шаблоне "Серверная часть для
клиентской части" (BFF), то есть шлюзы реализуют только те API, которые нужны конкретному
клиентскому приложению. Но в более крупных приложениях следует пойти немного дальше и
использовать границы бизнес-процессов в качестве второго фактора разделения шлюзов API.
Обратный прокси- сервер или маршрутизация шлюза . Шлюз API предоставляет обратный прокси-
сервер для маршрутизации или перенаправления запросов (маршрутизация уровня 7, обычно это HTTP-
запросы) к конечным точкам внутренних микрослужб. Шлюз предоставляет единую конечную точку
(URL-адрес) для клиентских приложений, а внутри сопоставляет запросы от них с конкретными группами
внутренних микрослужб. Эта возможность маршрутизации помогает отделить клиентские приложения
от микрослужб, но она не менее удобна при обновлении монолитного API. Между этим монолитным API и
клиентскими приложениями размещается шлюз API, что позволяет добавлять новые API в формате
микрослужб и продолжать использовать монолитный API вплоть до его разделения на множество
микрослужб. Благодаря шлюзу API для клиентских приложений неважно, как реализованы конкретные
API-интерфейсы: в виде внутренних микрослужб или монолитных API. И что более важно, в процессе
развития, рефакторинга и разделения монолитного API на микрослужбы шлюз API защищает клиентские
приложения от любых изменений URI.
В зависимости от того, какой продукт вы используете в качестве шлюза API, он может поддерживать или
не поддерживать агрегирование. Но во многих случаях более гибким подходом будет создание
микрослужб агрегирования в пределах шлюза API, и тогда ее нужно выполнять в отдельном коде (то есть
в коде C#).
Аутентификация и авторизация
интеграция средства обнаружения служб;
Кэширование откликов
политики повторных попыток, размыкатель цепи и качество обслуживания;
ограничение скорости и регулирование;
балансировка нагрузки;
ведение журнала, трассировка, корреляция;
преобразования заголовков, строк запроса и утверждений;
Добавление IP-адресов в список разрешений
Служба управления API Azure удовлетворяет ваши потребности в отношении шлюза API и управления,
такие как ведение журнала, обеспечение безопасности, контроль использования и т. д. В этом случае при
использовании такого продукта, как управление API Azure, наличие одного шлюза API не так рискованно,
так как такие виды шлюзов API "тоньше". Это означает , что вы не сможете реализовать пользовательский
код C#, который сможет развиваться в сторону монолитного компонента.
Такой шлюз API обычно выступает в роли обратного прокси-сервера для приема данных, позволяя
отделить API от внутренних микрослужб и реализовать авторизацию для всех опубликованных API на
этом едином уровне.
Аналитические сведения, доступные из системы управления API, помогут вам понять, как используются
ваши API и насколько эффективно они работают. Для этого вы можете просматривать отчеты
практически в режиме реального времени и выявлять тенденции, которые могут повлиять на ваш бизнес.
Кроме того, вы можете вести журналы запросов и ответов как для интерактивного, так и для
автономного анализа.
С помощью управления API Azure вы можете защитить свои интерфейсы API с помощью ключей,
маркеров и фильтрации IP-адресов. Эти возможности позволяют обеспечить гибкие и точные квоты и
ограничения скорости, изменить форму и поведение ваших API с помощью политик и улучшить
производительность с помощью кэширования ответов.
Ocelot
Ocelot — это упрощенный шлюз API, рекомендуемый для более простых случаев. Шлюз API Ocelot с
открытым кодом на основе .NET Core специально разработан для архитектуры микрослужб, в которой
нужны единые точки входа в систему. Он не требует большого количества ресурсов, быстро работает ,
легко масштабируется, а также наряду с многими другими функциями поддерживает маршрутизацию и
проверку подлинности.
Ocelot используется в примере приложения eShopOnContainers 2.0 в первую очередь потому, что этот
простой шлюз API на основе .NET Core можно развернуть в той же среде развертывания приложений, где
размещаются микрослужбы и контейнеры, такие как узел Docker, Kubernetes и т. д. Так как этот шлюз
основан на .NET Core, он одинаково хорошо работает на платформах Windows или Linux.
На схеме выше представлен пользовательский шлюз API, выполняемый в контейнерах. Ocelot можно
точно так же запустить в контейнере для приложения на основе микрослужб.
Кроме него, существует много других продуктов с функциональностью шлюза API, например Apigee,
Kong, MuleSoft, WSO2. Также есть много продуктов, например Linkerd и Istio, реализующих функции
управления входящими данными.
Использование шлюза API микрослужб создает возможную дополнительную единую точку отказа.
Шлюз API может привести к увеличению времени ответа из-за дополнительного сетевого вызова.
Однако этот дополнительный вызов обычно оказывает меньшее влияние, чем целый клиентский
интерфейс, который постоянно взаимодействует с внутренними микрослужбами.
При отсутствии должного масштабирования шлюз API может стать узким местом.
Если шлюз API разрабатывается одной командой, это может быть узким местом разработки. Это
еще одна причина, по которой лучше использовать несколько специализированных шлюзов API,
которые реализуют различные потребности клиента. Также можно внутренне разделить шлюз API
на несколько областей или уровней, которые принадлежат другим командам, работающим над
внутренними микрослужбами.
Дополнительные ресурсы
Крис Ричардсон (Chris Richardson). Шаблон: шлюз API, серверная часть для внешнего
интерфейса
https://microservices.io/patterns/apigateway.html
Шаблон шлюза API
https://docs.microsoft.com/azure/architecture/microservices/gateway
Шаблон агрегирования и компоновки
https://microservices.io/patterns/data/api-composition.html
Управление API Azure
https://azure.microsoft.com/services/api-management/
Уди Дахан (Udi Dahan). Объединение на основе служб
https://udidahan.com/2014/07/30/service-oriented-composition-with-video/
Клеменс Вастерс (Clemens Vasters). Messaging and Microser vices ( Обмен сообщениями
и микрослужбы) на GOTO 2016 ( видео)
https://www.youtube.com/watch?v=rXi5CLjIQ9k
API Gateway в двух словах (серия руководств по API Gateway ASP.NET Core)
https://www.pogsdotnet.com/2018/08/api-gateway-in-nutshell.html
НА ЗА Д ВПЕРЕД
Взаимодействие в архитектуре микрослужб
02.11.2021 • 8 minutes to read
Сообщество микрослужб исповедует философию "умные конечные точки и глупые каналы". Этот слоган
рекомендует создавать структуру, где отдельные микрослужбы будут минимально зависеть друг от
друга и иметь максимальную внутреннюю согласованность. Как уже говорилось, каждая микрослужба
обладает собственными данными и собственной логикой предметной области. Но микрослужбы,
составляющие цельное приложение, обычно организуются с помощью связей по принципу REST, а не
сложных протоколов, таких как WS-*, и гибких, управляемых событиями взаимодействий вместо
централизованных оркестраторов бизнес-процессов.
Обычно используются два протокола — запросы и ответы HTTP с исходными API (в основном для
запросов) и легкие асинхронные сообщения при передаче обновлений в несколько микрослужб. Более
подробно это описано в следующих разделах.
Типы связи
Клиент и службы могут взаимодействовать через различные типы связи в зависимости от сценария и
целей. Эти типы связи можно разделить на два направления.
Синхронный протокол. HTTP — это синхронный протокол. Клиент отправляет запрос и ожидает
ответа от службы. Это не зависит от выполнения кода клиента, которое может быть синхронным
(поток заблокирован) или асинхронным (поток не заблокирован, ответ в конечном итоге будет
отправлен). Здесь важно, что протокол (HTTP/HTTPS) является синхронным и код клиента сможет
продолжить выполнение задачи только после получения ответа от HTTP-сервера.
Асинхронный протокол. Другие протоколы, например AMQP (протокол, поддерживаемый многими
операционными системами и облачными средами), используют асинхронные сообщения. Код
клиента или отправитель сообщения обычно не ожидает ответа. Он просто отправляет
сообщение, как при отправке сообщения в очередь RabbitMQ или другого брокера сообщений.
Один получатель. Каждый запрос должен обрабатываться только одним получателем или
службой. Например, шаблон Command.
Приложение на базе микрослужб часто использует комбинацию этих стилей взаимодействия. Наиболее
распространенный тип — взаимодействие с одним получателем по синхронному протоколу, например
HTTP или HTTPS, при вызове обычной службы веб-API HTTP. Для асинхронного взаимодействия между
микрослужбами обычно используются протоколы сообщений.
Более того, наличие зависимостей HTTP между микрослужбами, как при создании длинных циклов
запрос-ответ с цепочкой HTTP-запросов, как показано в первой части рисунка 4-15, не только нарушит
автономность микрослужб, но и повлияет на их производительность, если одна из служб в цепочке не
будет работать правильно.
Чем больше синхронных зависимостей между микрослужбами, например запросов, тем больше время
отклика в клиентских приложениях.
Как показано на схеме выше, при синхронном обмене данными "цепочка" запросов создается между
микрослужбами при обслуживании запроса клиента. Это антишаблон. В асинхронной связи
микрослужбы используют асинхронные сообщения или опрос по HTTP для взаимодействия с другими
микрослужбами, но запрос клиента обрабатывается сразу.
И, наконец (и именно на этом этапе создания микрослужб возникают проблемы), если исходной
микрослужбе нужны данные, принадлежащие другим микрослужбам, не создавайте синхронные запросы
этих данных. Лучше реплицировать или распространять эти данные (только необходимые атрибуты) в
базу данных исходной службы, используя итоговую согласованность (обычно с помощью событий
интеграции, как описано в следующих разделах).
Как уже упоминалось в статье Определение границ модели предметной области для каждой
микрослужбы, дублирование данных в нескольких микрослужбах допускается. Более того, таким
образом вы сможете перевести данные на конкретный язык, используя термины этой области или
ограниченного контекста. Например, в приложении eShopOnContainers есть микрослужба identity-api ,
которая отвечает за большую часть данных пользователя с сущностью, называемой User . Но если вам
нужно хранить данные о пользователе в микрослужбе Ordering , вы используете отдельную сущность
под названием Buyer . Сущность Buyer имеет тот же идентификатор, что и исходная сущность User , но
содержит лишь некоторые атрибуты, необходимые для предметной области Ordering , а не весь профиль
пользователя.
Стили взаимодействия
Вы можете выбирать разные протоколы для взаимодействия в зависимости от желаемого типа
взаимодействия. В качестве механизма взаимодействия с помощью синхронных запросов и ответов
обычно используются HTTP и REST, особенно если вы публикуете службы за пределами узла Docker или
кластера микрослужб. Если взаимодействие между службами осуществляется в пределах узла Docker или
кластера микрослужб, вы можете использовать двоичный формат взаимодействия (например, WCF с
помощью TCP и двоичного формата). Кроме того, вы можете использовать механизмы асинхронного
взаимодействия на основе сообщений, например AMQP.
Существует также несколько форматов сообщений, например JSON или XML, или даже двоичных
форматов, которые могут быть более эффективными. Если вы выбрали нестандартный двоичный
формат , возможно, службы с этим форматом не следует публиковать. Вы можете использовать
нестандартный формат для внутреннего взаимодействия между микрослужбами. Например, при
взаимодействии между микрослужбами на узле Docker или кластере микрослужб (в оркестраторах
Docker) или для собственных клиентских приложений, которые обращаются к микрослужбам.
Операция запрос-ответ с использованием HTTP и REST
Если клиент использует взаимодействие типа "запрос-ответ ", он посылает запрос к службе, которая
обрабатывает этот запрос и отправляет ответ. Взаимодействие типа "запрос-ответ " особенно хорошо
подходит для запроса данных от клиентских приложений для пользовательского интерфейса в режиме
реального времени. Поэтому в архитектуре микрослужб лучше всего использовать этот механизм
взаимодействия для запросов, как показано на рис. 4-16.
Рис. 4-16 . Использование взаимодействия типа "запрос-ответ " по протоколу HTTP (синхронно или
асинхронно)
Когда клиент использует взаимодействие типа "запрос-ответ ", он предполагает , что ответ придет
быстро, меньше чем через секунду или максимум через несколько секунд. Если ответ задерживается,
необходимо реализовать асинхронное взаимодействие на основе шаблонов обмена сообщениями и
технологий обмена сообщениями. Этот подход рассматривается в следующем разделе.
Популярный стиль архитектуры для взаимодействия типа "запрос-ответ " — это REST. Этот подход
основан на HTTP-протоколе и тесно связан с ним. Он принимает HTTP-команды, например GET, POST и
PUT. REST — это самый распространенный архитектурный подход к взаимодействию при создании служб.
Службы REST можно использовать при разработке служб веб-API ASP.NET Core.
Использование служб HTTP REST в качестве IDL имеет дополнительные преимущества. Например, если вы
используете метаданные Swagger для описания API службы, вы можете применять средства, создающие
заглушки клиента, которые могут обнаруживать и использовать ваши службы напрямую.
Дополнительные ресурсы
Мартин Фоулер (Mar tin Fowler). Модель зрелости Ричардсона Описание модели REST.
https://martinfowler.com/articles/richardsonMaturityModel.html
Swagger Официальный сайт.
https://swagger.io/
Push-уведомления и связь в режиме реального времени по протоколу HTTP
Другой вариант (обычно используется не для тех же целей, что и REST) — это связь "один ко многим" в
режиме реального времени с платформами более высокого уровня, например ASP.NET SignalR, и такими
протоколами, как WebSockets.
Как показано на рисунке 4-17, связь в режиме реального времени по протоколу HTTP означает , что
серверный код может принудительно отправлять содержимое подключенным клиентам, когда данные
становятся доступны, а не ждать, пока клиент запросит новые данные.
Рис. 4-17 . Асинхронное взаимодействие "один ко многим" на основе сообщений в режиме реального
времени
SignalR — это лучший способ достичь взаимодействия в реальном времени для передачи содержимого
клиентам с внутреннего сервера. Поскольку взаимодействие происходит в режиме реального времени,
изменения отображаются в клиентских приложениях почти моментально. Обычно это обрабатывается
таким протоколом, как WebSockets, с помощью множества подключений WebSockets (по одному для
каждого клиента). Типичный пример — служба передает изменение счета матча множеству клиентских
веб-приложений одновременно.
НА ЗА Д ВПЕРЕД
Асинхронное взаимодействие на основе
сообщений
02.11.2021 • 7 minutes to read
Сообщение состоит из заголовка (метаданные, например, идентификатор или данные для обеспечения
безопасности) и текста. Обычно сообщения отправляются с использованием асинхронного протокола,
например AMQP.
Есть еще правило, которого следует придерживаться, насколько это возможно. Между внутренними
службами следует использовать только асинхронный обмен сообщениями, а синхронное взаимодействие
(например, HTTP) использовать только для клиентских приложений, работающих со службами
интерфейса (шлюзами API и микрослужбами первого уровня).
Существует два типа асинхронного обмена сообщениями: взаимодействие на основе сообщений с одним
получателем и взаимодействие с несколькими получателями. В следующих разделах содержатся
дополнительные сведения об этих типах обмена.
После того как вы начнете взаимодействие на основе сообщений (с использованием команд или
событий), вам не следует использовать этот тип взаимодействия вместе с синхронным обменом по
протоколу HTTP.
Когда команды поступают из клиентских приложений, они могут быть реализованы в виде синхронных
команд HTTP. Используйте команды на основе сообщений, когда требуется высокая масштабируемость,
или когда вы уже запустили бизнес-процесс на основе сообщений.
При взаимодействии на основе публикаций и подписок вы, возможно, будете использовать интерфейс
шины событий при публикации событий для всех подписчиков.