архитектура приложения asp net core
Разработка современных веб-приложений с помощью ASP.NET Core и Azure
Выпуск 5.0 — обновлен до ASP.NET Core 5.0
Обновления книги и вклад сообщества см. в журнале изменений.
Подразделение корпорации Майкрософт
Redmond, Washington 98052-6399
© Корпорация Майкрософт (Microsoft Corporation), 2021.
Все права защищены. Запрещается полное или частичное воспроизведение или передача настоящей книги в любом виде или любыми средствами без письменного разрешения издателя.
Эта книга предоставляется на условиях «как есть» и выражает взгляды и мнения автора. Взгляды, мнения и сведения, содержащиеся в этой книге, включая URL-адреса и другие ссылки на веб-сайты, могут изменяться без уведомления.
Некоторые приведенные в книге примеры служат только для иллюстрации и являются вымышленными. Все совпадения с реальными наименованиями, людьми и любыми другими предметами являются непреднамеренными и случайными.
Microsoft и товарные знаки, перечисленные на странице «Товарные знаки» на сайте https://www.microsoft.com, являются товарными знаками группы компаний Майкрософт.
Mac и macOS являются товарными знаками Apple Inc.
Логотип Docker с изображением кита является зарегистрированным товарным знаком Docker, Inc. Используется с разрешения.
Все другие наименования и логотипы являются собственностью своих законных владельцев.
Майра Вензел (Maira Wenzel)
Ссылки действий
Эта электронная книга также доступна в формате PDF (только на английском языке) Скачать
Клонируйте эталонное приложение eShopOnWeb на GitHub или создайте для него вилку
Вступление
Поддержка разных платформ.
Использование контейнеров Docker.
Требования к обеспечению высокой производительности и масштабируемости.
Все больше организаций предпочитают размещать свои веб-приложения в облаке с помощью таких служб, как Microsoft Azure. Рекомендуется рассмотреть возможность размещения приложения в облаке, если для приложения или организации важны следующие моменты:
Сокращение инвестиций в центр обработки данных (оборудование, программное обеспечение, помещения, коммунальные услуги, управление серверами и т. д.)
Гибкие цены (оплата за фактически используемые, а не простаивающие ресурсы).
Улучшенная мобильность приложений, простота изменения места и способа их развертывания.
Гибкая емкость, масштабирование в соответствии с фактическими потребностями.
Создание веб-приложений с помощью ASP.NET Core, размещенных в Azure, имеет множество конкурентных преимуществ по сравнению с традиционными альтернативами. Платформа ASP.NET Core оптимизирована для современных методик разработки веб-приложений и сценариев размещения в облаке. В этом руководстве вы узнаете, как спроектировать приложения ASP.NET Core, чтобы максимально эффективно воспользоваться этими возможностями.
Версия
Этот документ является полным руководством по созданию монолитных веб-приложений с помощью ASP.NET Core и Azure. В этом контексте монолитность означает то, что эти приложения развертываются как единое целое, а не как коллекция интерактивных служб и приложений.
Кому необходимо это руководство
Это руководство предназначено главным образом для разработчиков, руководителей отделов разработки и архитекторов, заинтересованных в создании современных веб-приложений с помощью технологий и служб Майкрософт в облаке.
Вторичной аудиторией являются лица, ответственные за принятие технических решений, которые уже знакомы с ASP.NET или Azure и которым требуются сведения о целесообразности обновления до ASP.NET Core для разработки новых и поддержки существующих проектов.
Как использовать это руководство
При необходимости вы можете порекомендовать это руководство членам своей команды, чтобы и они были в курсе всех важных аспектов. Если все заинтересованные лица будут использовать общий набор терминологии и придерживаться основополагающих принципов, архитектурные модели и практики будут применяться более последовательно.
Архитектура приложений
Onion-архитектура. Часть 1
Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Термин «Onion Architecture» («луковая» архитектура) был предложен Джеффри Палермо (Jeffrey Palermo) еще в 2008 году. Спустя годы данная концепция стала довольно популярной и является одной из наиболее применяемых типов архитектуры при построении приложения на ASP.NET.
Количество уровней может отличаться, но в центре всегда находится модель домена (Domain Model), то есть те классы моделей, которые используются в приложении и объекты которых хранятся в базе данных:
Первый уровень вокруг модели домена образуют интерфейсы, которые управляют работой с моделью домена. Обычно это интерфейсы репозиториев, через которые мы взаимодействуем с базой данных.
Внешний уровень представляет такие компоненты, которые очень часто изменяются. Обычно внешний уровень образуют пользовательский интерфейс, тесты, какие-то вспомогательные классы инфраструктуры приложения. К этому уровню также относятся конкретные реализации интерфейсов, объявленных на нижележащих уровнях. Например, реализация интерфейса репозитория, который объявлен на уровне Domain Services. Вообще все внутрение уровни, которые можно объединить в Application Core, определяют только интерфейсы, а конкретная реализация этих интерфейсов располагается на внешнем уровне.
Для более подробного рассмотрения данного типа архитектуры создадим обычный проект ASP.NET MVC 5, который будет называться OnionApp.
Добавим в новый проект класс, представляющий книгу, который и будут представлять Domain Model:
Этот интерфейс и составляет уровень Domain Services и зависит от уровня Domain Model.
И на данный момент проекты выглядят так:
При создании архитектуры приложения надо понимать, что реальное количество уровней здесь весьма условно. В зависимости от масштаба задач уровней может быть и больше, и меньше. Однако важно понимать сам принцип, что в центре у нас модели домена, а все остальное зависит от них. Каждый внешний уровень может зависеть от внутреннего, но не наоборот.
И добавим в этот проект интерфейс IOrder:
Данный проект будет реализовывать интерфейсы, объявленные на нижних уровнях, и связывать их с хранилищем данных. В качестве хранилища данных будет использоваться бд MS SQL Server, с которой мы будем взаимодействовать через Entity Framework. Поэтому добавим в этот проект через nuGet все пакеты Entity Framework. Также добавим в проект ссылки на проекты OnionApp.Domain.Core и OnionApp.Domain.Interfaces.
После этого добавим в проект новый класс OrderContext :
Также добавим класс репозитория BookRepository:
Общие архитектуры веб-приложений
«Если вы считаете хорошую архитектуру слишком дорогой, попробуйте использовать плохую». — Брайан Фут (Brian Foote) и Джозеф Йодер (Joseph Yoder)
Что собой представляет монолитное приложение?
Монолитное приложение полностью замкнуто в контексте поведения. Во время работы оно может взаимодействовать с другими службами или хранилищами данных, однако основа его поведения реализуется в собственном процессе, а все приложение обычно развертывается как один элемент. Для горизонтального масштабирования такое приложение обычно целиком дублируется на нескольких серверах или виртуальных машинах.
Комплексные приложения
Архитектура приложения содержит как минимум один проект. В таком случае вся логика приложения заключена в одном проекте, компилируется в одну сборку и развертывается как один элемент.
Любой создаваемый в Visual Studio или из командной строки проект ASP.NET Core изначально будет представлять собой комплексный монолитный проект. В нем будет заключено все поведение приложения, включая презентацию данных, бизнес-логику и логику доступа к данным. На рис. 5-1 показана файловая структура приложения, состоящего из одного проекта.
Рис. 5-1. Приложение ASP.NET Core, состоящее из одного проекта.
В сценарии с одним проектом разделение задач реализуется с помощью папок. Используемый по умолчанию шаблон включает отдельные папки для обязанностей шаблона MVC (модели, представления и контроллеры), а также дополнительные папки для данных и служб. При такой организации детали презентации данных в максимально возможной степени размещаются в папке представлений (Views), а детали реализации доступа к данным должны быть ограничены классами, содержащимися в папке данных (Data). Бизнес-логика при этом размещается в службах и классах, находящихся в папке моделей (Models).
Несмотря на свою простоту, монолитное решение с одним проектом имеет определенные недостатки. По мере увеличения размера и сложности проекта будет расти число файлов и папок. Задачи, связанные с пользовательским интерфейсом (модели, представления, контроллеры), размещаются в разных папках, которые не упорядочены по алфавиту. С добавлением в отдельные папки конструкций уровня пользовательского интерфейса, например фильтров или связывателей модели, ситуация только ухудшается. Бизнес-логика теряется в папках моделей (Models) и служб (Services), в результате чего невозможно четко определить, какие классы в каких папках должны зависеть от других классов. Подобная неэффективная организация на уровне проекта часто приводит к получению плохо структурированного кода.
Для решения подобных проблем приложения часто организуются в виде решений, состоящих из множества проектов, где каждый проект размещается в отдельном слое приложения.
Что представляют собой слои?
По мере увеличения сложности приложения для эффективного управления им может применяться разбиение по обязанностям и задачам. Такой подход соответствует принципу разделения задач и помогает сохранить организацию расширяющейся базы кода, благодаря чему разработчики могут быстро определять, где именно реализованы определенные функции. Многослойная архитектура имеет также целый ряд других преимуществ.
Благодаря упорядочению кода с помощью слоев общие низкоуровневые функции могут многократно использоваться по всему приложению. Это крайне важно, поскольку такой подход требует меньшего объема кода и, за счет стандартизации приложения на уровне одной реализации, соответствует принципу «Не повторяйся».
В приложениях с многослойной архитектурой могут устанавливаться ограничения на взаимодействие между слоями. Такая архитектура помогает реализовать инкапсуляцию. При изменении или замене слоя будут затронуты только те слои, которые работают непосредственно с ним. Ограничивая зависимости слоев друг от друга, можно уменьшить последствия внесения изменений, в результате чего единичное изменение не будет влиять на все приложение.
Применение слоев (и инкапсуляция) позволяет заметно упростить замену функциональных возможностей в рамках приложения. Например, приложение может изначально использовать собственную базу данных SQL Server для сохраняемости, а впоследствии перейти на стратегию сохранения состояния на основе облака или веб-API. Если в приложении надлежащим образом инкапсулирована реализация сохраняемости на логическом слое, этот слой SQL Server может быть заменен новым, где будет реализовываться тот же открытый интерфейс.
Помимо возможности замены реализаций в связи с последующими изменениями, применение слоев в приложении также позволяет менять реализации в целях тестирования. Вместо написания тестов, которые применяются к слоям реальных данных или пользовательского интерфейса приложения, во время тестирования они заменяются фиктивными реализациями, которые демонстрируют известную реакцию на запросы. Как правило, это значительно упрощает написание тестов и ускоряет их выполнение по сравнению с тестированием в реальной инфраструктуре приложения.
Разделение на логические слои широко распространено и помогает упорядочить код приложений предприятия. Сделать это можно несколькими способами.
Слои обеспечивают логический уровень разделения в приложении. Если логика приложения физически распределена между несколькими серверами или процессами, такие раздельные физические целевые объекты развертывания называются уровнями. Таким образом, не только возможно, но и широко распространено развертывание N-слойных приложений на одном уровне.
Традиционные приложения с N-слойной архитектурой
Общепринятая организация логики приложения по слоям показана на рис. 5-2.
Рис. 5-2. Слои типового приложения.
Как правило, в приложении определяются слои пользовательского интерфейса, бизнес-логики и доступа к данным. В рамках такой архитектуры пользователи выполняют запросы через слой пользовательского интерфейса, который взаимодействует только со слоем бизнес-логики. Слой бизнес-логики, в свою очередь, может вызывать слой доступа к данным для обработки запросов. Слой пользовательского интерфейса не должен выполнять запросы напрямую к слою доступа к данным и какими-либо другими способами напрямую взаимодействовать с функциями сохраняемости. Аналогичным образом, слой бизнес-логики должен взаимодействовать с функциями сохраняемости только через слой доступа к данным. Таким образом, для каждого слоя четко определена своя обязанность.
Одним из недостатков традиционного многослойного подхода является то, что обработка зависимостей во время компиляции осуществляется сверху вниз. Это значит, что слой пользовательского интерфейса зависит от слоя бизнес-логики, который, в свою очередь, зависит от слоя доступа к данным. Это значит, что слой бизнес-логики, который обычно содержит ключевые функции приложения, зависит от деталей реализации доступа к данным (и зачастую от наличия самой базы данных). Тестирование бизнес-логики в такой архитектуре зачастую затруднено и требует наличия тестовой базы данных. Для решения этой проблемы может применяться принцип инверсии зависимостей, как описывается в следующем разделе.
На рис. 5-3 показан пример решения, в котором приложение разделено на три проекта (или слоя) в соответствии с определенными обязанностями.
Рис. 5-3. Простое монолитное приложение, состоящее из трех проектов.
Несмотря на то, что в целях упорядочения в этом приложении используется несколько проектов, оно по-прежнему развертывается как единый элемент, и его клиенты взаимодействуют с ним как с одним веб-приложением. Это позволяет реализовать крайне простой процесс развертывания. На рис. 5-4 показано, как такое приложение можно разместить с использованием Azure.
Рис. 5-4. Простое развертывание веб-приложения Azure
По мере развития приложения могут потребоваться более сложные и надежные решения для развертывания. На рис. 5-5 показан пример более сложного плана развертывания, который поддерживает дополнительные возможности.
Рис. 5-5. Развертывание веб-приложения в службе приложений Azure
Разбиение этого проекта на несколько проектов на основе обязанностей позволяет повысить удобство поддержки приложения.
Такой элемент поддерживает вертикальное и горизонтальное масштабирование, что позволяет использовать преимущества облачного масштабирования по запросу. Под вертикальным масштабированием понимается увеличение числа ЦП, объема памяти, места на диске и других ресурсов на серверах, где размещается приложение. Горизонтальное масштабирование заключается в добавлении дополнительных экземпляров таких физических серверов, виртуальных машин или контейнеров. Если приложение размещается на нескольких экземплярах, для распределения запросов между экземплярами приложения используется система балансировки нагрузки.
Самый простой подход к масштабированию веб-приложения в Azure заключается в ручной настройке масштабирования в плане службы приложений для приложения. На рис. 5-6 показан экран панели мониторинга Azure, предназначенный для настройки числа экземпляров, обслуживающих приложение.
Рис. 5-6. Масштабирование плана службы приложений в Azure.
Чистая архитектура
Приложения, использующие принципы инверсии зависимостей и проблемно-ориентированного проектирования, имеют схожую архитектуру. На протяжении многих лет она носила самые разные названия. Сначала это была шестигранная архитектура, на смену которой пришла архитектура портов и адаптеров. На современном этапе она называется многослойной или чистой архитектурой. В этой электронной книге используется термин «чистая архитектура».
Эталонное приложение eShopOnWeb использует подход на основе чистой архитектуры для организации кода в проекты. Вы можете найти шаблон решения, который можно использовать в качестве отправной точки для собственных решений ASP.NET Core в репозитории ardalis/cleanarchitecture на GitHub.
В рамках чистой архитектуры центральным элементом приложения являются его бизнес-логика и модель. В этом случае бизнес-логика не зависит от доступа к данным или другим инфраструктурам, то есть стандартная зависимость инвертируется: инфраструктура и детали реализации зависят от ядра приложения. Эта функциональность достигается путем определения абстракций или интерфейсов в ядре приложения, которые реализуются типами, определенными в слое инфраструктуры. Такую архитектуру обычно рисуют в виде серии окружностей с общим центром, которая внешне напоминает срез луковицы. На рис. 5-7 показан пример такого стиля представления архитектуры.
Рис. 5-7. Чистая архитектура (многослойное представление)
На этой схеме зависимости направлены из самой внутренней окружности. Ядро приложения называется так потому, что находится в самом центре этой схемы. Как видно на схеме, ядро приложения не имеет зависимостей от других слоев приложения. Сущности и интерфейсы приложения находятся в самом центре. Сразу после них, но все еще в пределах ядра приложения, расположены доменные службы, которые обычно реализуют интерфейсы, определенные во внутренней окружности. За пределами ядра приложения располагаются слои пользовательского интерфейса и инфраструктуры, которые зависят от ядра приложения, но не друг от друга (обязательно).
На рис. 5-8 показана более привычная горизонтальная схема слоев, которая лучше отражает зависимости между слоем пользовательского интерфейса и другими слоями.
Рис. 5-8. Чистая архитектура (горизонтальное представление слоев)
Обратите внимание, что сплошные стрелки соответствуют зависимостям времени компиляции, а пунктирные — зависимостям, которые существуют только во время выполнения. В рамках чистой архитектуры слой пользовательского интерфейса работает с интерфейсами, которые определены в ядре приложения во время компиляции, и в идеальном случае не должен знать ничего о типах реализации, определенных в слое инфраструктуры. Тем не менее во время выполнения эти типы реализации необходимы для выполнения приложения, поэтому они должны существовать и быть привязаны к интерфейсам ядра приложения посредством внедрения зависимостей.
На рис. 5-9 показано более подробное представление архитектуры приложения ASP.NET Core, построенного с соблюдением этих рекомендаций.
Рис. 5-9. Схема чистой архитектуры ASP.NET Core.
Поскольку ядро приложения не зависит от инфраструктуры, для этого слоя легко писать автоматические модульные тесты. На рис. 5-10 и 5-11 показано, как эти тесты вписываются в такую архитектуру.
Рис. 5-10. Изолированное модульное тестирование ядра приложения.
Рис. 5-11. Интеграционное тестирование реализаций инфраструктуры с внешними зависимостями.
Поскольку слой пользовательского интерфейса не имеет прямых зависимостей от типов, определенных в проекте инфраструктуры, будет так же просто менять реализации в целях тестирования или в случае изменения требований к приложению. ASP.NET Core предлагает встроенную поддержку внедрения зависимостей, в связи с чем такая архитектура представляет собой оптимальный подход к структурированию нетривиальных монолитных приложений.
Для монолитных приложений проекты ядра приложения, инфраструктуры и пользовательского интерфейса выполняются как единое приложение. Во время выполнения архитектура приложения будет выглядеть так, как показано на рис. 5-12.
Рис. 5-12. Пример архитектуры приложения ASP.NET Core во время выполнения.
Упорядочение кода в рамках чистой архитектуры
В решении с чистой архитектурой для каждого проекта четко определены обязанности. Фактически, каждому проекту будут принадлежать определенные типы, а в проектах будут представлены соответствующие этим типам папки.
Ядро приложения
Ядро приложения содержит бизнес-модель, которая включает в себя сущности, службы и интерфейсы. Такие интерфейсы включают абстракции для операций, которые будут выполняться с использованием архитектуры, включая операции доступа к данным или файловой системе, сетевые вызовы и т. д. В некоторых случаях службы или интерфейсы, определенные в этом слое, должны работать с типами, не являющимися типами сущностей, которые не имеют зависимостей от пользовательского интерфейса или инфраструктуры. Они могут определяться как простые объекты передачи данных.
Типы ядра приложения
Инфраструктура
Как правило, проект инфраструктуры включает реализацию доступа к данным. В типовом веб-приложении ASP.NET Core эта реализация включает Entity Framework (EF) DbContext, любые определенные объекты Migration EF Core, а также классы реализации доступа к данным. Наиболее распространенный подход к абстрагированию кода реализации доступа к данным заключается в использовании конструктивного шаблона репозитория.
Помимо реализации доступа к данным, проект инфраструктуры должен также включать реализации служб, которые должны взаимодействовать с инфраструктурными задачами. Эти службы должны реализовывать интерфейсы, определенные в ядре приложения. Таким образом, инфраструктура должна содержать ссылку на проект ядра приложения.
Типы инфраструктуры
Уровень пользовательского интерфейса
Слой пользовательского интерфейса в приложении MVC ASP.NET Core выступает в качестве точки входа для приложения. Этот проект должен ссылаться на слой ядра приложения, а его типы должны взаимодействовать с инфраструктурой строго через интерфейсы, определенные в ядре приложения. В слое пользовательского интерфейса не должны разрешаться прямое создание экземпляров для типов слоя инфраструктуры, а также их статические вызовы.
Типы слоев пользовательского интерфейса
Класс Startup отвечает за настройку приложений и запись типов реализации в интерфейсы, обеспечивая корректную работу внедрения зависимостей во время выполнения.
Чтобы привязать внедрение зависимостей в ConfigureServices в файле Startup.cs проекта пользовательского интерфейса, в этом проекте может потребоваться ссылка на проект инфраструктуры. Эту зависимость можно исключить. Проще всего это сделать с помощью настраиваемого контейнера внедрения зависимостей. В рамках этого примера применяется простейший подход, при котором разрешаются ссылки из проекта пользовательского интерфейса на проект инфраструктуры.
Монолитные приложения и контейнеры
Вы можете создать одно монолитное веб-приложение или службу и развернуть их как контейнер. В рамках приложения монолитность может не соблюдаться, однако будет реализована организация на основе нескольких библиотек, компонентов или слоев. Внешне оно будет представлять собой единый контейнер — единый процесс, единое веб-приложение или единую службу.
Для управления этой моделью вы развертываете один контейнер, представляющий собой приложение. Для увеличения масштаба просто добавьте дополнительные копии с подсистемой балансировки нагрузки спереди. Управлять одним развертыванием в одном контейнере или виртуальной машине гораздо проще.
Вы можете включить в один контейнер несколько компонентов, библиотек или внутренних слоев, как показано на рис. 5-13. Такой монолитный шаблон может конфликтовать с принципом контейнера: «контейнер выполняет одно дело и в одном процессе«.
Недостаток этого подхода становится очевидным, когда приложение разрастается и его необходимо масштабировать. Если масштабируется приложение целиком, все получится. Но в большинстве случаев необходимо масштабировать всего несколько частей приложения, пока другие компоненты работают нормально.
В примере приложения для электронной торговли, вероятнее всего, потребуется масштабирование компонента со сведениями о товарах. Клиенты чаще просматривают товары, чем приобретают их. Клиенты чаще складывают товары в корзину, чем оплачивают их. Не так много клиентов пишут комментарии или просматривают историю покупок. И у вас скорее всего может быть лишь несколько сотрудников в одном регионе, которые управляют содержимым и маркетинговыми кампаниями. При масштабировании монолитных решений весь код развертывается многократно.
Помимо того, что необходимо масштабировать все компоненты, изменения в одном компоненте требуют полного повторного тестирования всего приложения и полного повторного развертывания всех его экземпляров.
Монолитный подход нашел широкое распространение и используется многими организациями при разработке архитектуры. Во многих случаях это позволяет добиться желаемых результатов, однако иногда организация сталкивается с достигнутыми ограничениями. Во многих организациях приложения строились по такой модели, поскольку несколько лет назад с помощью существующих инструментов и инфраструктуры слишком сложно было создавать архитектуры, ориентированные на службы (SOA), и проблем не возникало, пока приложение не начинало разрастаться. Если ваша организация столкнулась с ограничениями монолитного подхода, следующим логичным шагом может стать разбиение приложения для более эффективного использования контейнеров и микрослужб.
Монолитные приложения в Microsoft Azure можно развертывать с использованием выделенных виртуальных машин для каждого экземпляра. С помощью масштабируемых наборов виртуальных машин Azure можно легко масштабировать виртуальные машины. Службы приложений Azure также могут выполнять монолитные приложения и легко масштабировать экземпляры, и вам не придется управлять виртуальными машинами. Службы приложений Azure также могут выполнять отдельные экземпляры контейнеров Docker, упрощая развертывание. С помощью Docker вы можете развернуть одну виртуальную машину на узле Docker и выполнять на ней несколько экземпляров. Для управления масштабированием можно использовать систему балансировки Azure, как показано на рис. 5-14.
Развертыванием на различных узлах можно управлять с помощью традиционных методов развертывания. Узлами Docker можно управлять с помощью вводимых вручную команд вида docker run или автоматизированно, например с помощью конвейеров непрерывной поставки (CD).
Развертывание монолитного приложения в контейнере
Использование контейнеров для управления развертываниями монолитных приложений имеет свои преимущества. Масштабировать экземпляры контейнера гораздо быстрее и проще, чем развертывать дополнительные виртуальные машины. Даже при использовании масштабируемых наборов виртуальных машин применяется основанный на экземплярах подход. При развертывании в виде экземпляров приложения управление конфигурацией приложения осуществляется в составе виртуальной машины.
Так как контейнеры по своей природе являются неизменяемыми, вам не придется беспокоиться о возможности повреждения виртуальной машины, когда скрипты обновления не учитывают некоторые оставшиеся на диске конфигурации или файлы.
Контейнеры Docker можно использовать для монолитного развертывания простых веб-приложений. Это позволяет оптимизировать конвейеры непрерывной интеграции и непрерывного развертывания, а также добиться успешного развертывания в рабочей среде. Вам больше не придется гадать, почему решение, выполняющееся на вашем компьютере, не выполняется в рабочей среде.
Архитектура на основе микрослужб имеет много преимуществ, но обратной стороной является повышение сложности. В некоторых случаях затраты перевешивают преимущества, и лучше прибегнуть к монолитному развертыванию приложения в одном контейнере или буквально нескольких.
Монолитное приложение может быть непросто разделить на отдельные микрослужбы. Микрослужбы должны работать независимо друг от друга для повышения отказоустойчивости приложения. Если приложение невозможно разложить на независимые функциональные составляющие, то его разделение лишь увеличит сложность.
Приложению пока может не требоваться независимое масштабирование компонентов. Многие приложения, когда им требуется использовать более одного экземпляра, относительно легко клонируют весь экземпляр. Дополнительный труд по разделению приложений на отдельные службы предоставляет минимум преимуществ, тогда как масштабирование полноценных экземпляров приложения — это простое и экономичное решение.
На ранних этапах развертывания приложения может отсутствовать ясное представление о том, где пролегают границы между функциональными областями. В процессе разработки продукта, обладающего минимальным необходимым набором возможностей, его естественное разделение на части может быть не очевидным. Некоторые из этих условий могут быть временными. Вы можете сначала создать монолитное приложение, а в дальнейшем отделить некоторые компоненты для разработки и развертывания в качестве микрослужб. Другие условия могут быть неотъемлемыми особенностями приложения. Это означает, что приложение в принципе невозможно разделить на несколько микрослужб.
Разделение приложения на множество отдельных процессов также приводит к накладным расходам. При разделении компонента на несколько процессов повышается сложность. Усложняются протоколы обмена данными. Вместо вызовов методов необходимо использовать асинхронное взаимодействие между службами. При переходе на архитектуру микрослужб необходимо добавить множество стандартных блоков, реализованных в версии приложения eShopOnContainers на основе микрослужб: обработку шины событий, отказоустойчивость и повторную отправку сообщений, итоговую согласованность и многое другое.
Во-первых, контейнерное развертывание означает, что каждый экземпляр приложения выполняется в одной и той же среде. Это относится и к среде разработки, в которой проводятся начальные этапы тестирования и разработки. Команда разработчиков может запускать приложение в контейнерной среде, которая аналогична рабочей.
Кроме того, контейнерные приложения обеспечивают более экономичное горизонтальное масштабирование. Контейнерная среда позволяет эффективнее организовывать совместное использование ресурсов, чем традиционные среды виртуальных машин.
Наконец, помещая приложение в контейнеры, вы разделяете бизнес-логику и сервер хранилища. По мере масштабирования приложения все контейнеры будут использовать один физический носитель данных. В качестве хранилища, как правило, используется сервер высокой доступности с базой данных SQL Server.
Поддержка Docker
Вы можете использовать Visual Studio 2017, чтобы добавить поддержку Docker в существующее приложение, щелкнув проект в обозревателе решений правой кнопкой мыши и выбрав Добавить > Поддержка Docker. Таким образом вы добавите необходимые файлы и внесете изменения в проект для их использования. В текущем примере eShopOnWeb эти файлы уже есть.
Файл docker-compose.yml на уровне решения содержит сведения о том, какие образы необходимо создать и какие контейнеры запустить. Этот файл позволяет использовать команду docker-compose для запуска нескольких приложений одновременно. В этом случае он запускает только веб-проект. Вы также можете с его помощью настроить зависимости, например отдельный контейнер базы данных.
Устранение неполадок с Docker
Обратите внимание, что запущенные контейнеры Docker могут быть привязаны к портам, которые в противном случае вы могли бы использовать в среде разработки. При попытке запустить или выполнить отладку приложения через порт, связанный с контейнером Docker, возникнет ошибка с сообщением о том, что сервер не может выполнить привязку к этому порту. Проблемы будет решена, если вы остановите контейнер.
Если вы хотите добавить поддержку Docker в приложение с помощью Visual Studio, убедитесь, что Docker Desktop при этом запущен. Если при запуске мастера средство Docker Desktop не выполняется, мастер будет работать неправильно. Кроме того, мастер проверяет выбранные контейнеры, чтобы правильно реализовать поддержку Docker. Чтобы добавить поддержку контейнеров Windows, необходимо запускать мастер при запущенном инструменте Docker Desktop с настроенными контейнерами Windows. Чтобы добавить поддержку контейнеров Linux, запускайте мастер при запущенном инструменте Docker с настроенными контейнерами Linux.