Общие архитектуры веб-приложений

Совет

Это фрагмент из книги, архитектор современных веб-приложений с ASP.NET Core и Azure, доступный в документации .NET или в виде бесплатного скачиваемого PDF-файла, который можно читать в автономном режиме.

Architect Modern Web Applications with ASP.NET Core and Azure eBook cover thumbnail.

"Если вы считаете, что хорошая архитектура дорого, попробуйте плохую архитектуру". - Брайан Колон и Джозеф Yoder

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

Что собой представляет монолитное приложение?

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

Комплексные приложения

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

Любой создаваемый в Visual Studio или из командной строки проект ASP.NET Core изначально будет представлять собой комплексный монолитный проект. В нем будет заключено все поведение приложения, включая презентацию данных, бизнес-логику и логику доступа к данным. На рис. 5-1 показана файловая структура приложения, состоящего из одного проекта.

A single project ASP.NET Core app

Рис. 5-1. Приложение ASP.NET Core, состоящее из одного проекта.

В сценарии с одним проектом разделение задач реализуется с помощью папок. Используемый по умолчанию шаблон включает отдельные папки для обязанностей шаблона MVC (модели, представления и контроллеры), а также дополнительные папки для данных и служб. При такой организации детали презентации данных в максимально возможной степени размещаются в папке представлений (Views), а детали реализации доступа к данным должны быть ограничены классами, содержащимися в папке данных (Data). Бизнес-логика при этом размещается в службах и классах, находящихся в папке моделей (Models).

Несмотря на свою простоту, монолитное решение с одним проектом имеет определенные недостатки. По мере увеличения размера и сложности проекта будет расти число файлов и папок. Задачи, связанные с пользовательским интерфейсом (модели, представления, контроллеры), размещаются в разных папках, которые не упорядочены по алфавиту. С добавлением в отдельные папки конструкций уровня пользовательского интерфейса, например фильтров или связывателей модели, ситуация только ухудшается. Бизнес-логика теряется в папках моделей (Models) и служб (Services), в результате чего невозможно четко определить, какие классы в каких папках должны зависеть от других классов. Подобная неэффективная организация на уровне проекта часто приводит к получению плохо структурированного кода.

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

Что собой представляют слои?

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

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

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

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

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

Разделение на логические слои широко распространено и помогает упорядочить код приложений предприятия. Сделать это можно несколькими способами.

Примечание.

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

Традиционные приложения с N-слойной архитектурой

Общепринятая организация логики приложения по слоям показана на рис. 5-2.

Typical application layers

Рис. 5-2. Слои типового приложения.

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

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

На рис. 5-3 показан пример решения, в котором приложение разделено на три проекта (или слоя) в соответствии с определенными обязанностями.

A simple monolithic application with three projects

Рис. 5-3. Простое монолитное приложение, состоящее из трех проектов.

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

Simple deployment of Azure Web App

Рис. 5-4. Простое развертывание веб-приложения Azure

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

Deploying a web app to an Azure App Service

Рис. 5-5. Развертывание веб-приложения в службе приложений Azure

Разбиение этого проекта на несколько проектов на основе обязанностей позволяет повысить удобство поддержки приложения.

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

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

App Service Plan scaling in Azure

Рис. 5-6. Масштабирование плана службы приложений в Azure.

Чистая архитектура

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

Эталонное приложение eShopOnWeb использует подход на основе чистой архитектуры для организации кода в проекты. Шаблон решения, который можно использовать в качестве отправной точки для собственных решений ASP.NET Core, находится в репозитории GitHub ardalis/cleanarchitecture. Кроме того, вы можете установить шаблон из NuGet.

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

Clean Architecture; onion view

Рис. 5-7. Чистая архитектура (многослойное представление)

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

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

Clean Architecture; horizontal layer view

Рис. 5-8. Чистая архитектура (горизонтальное представление слоев)

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

На рис. 5-9 показано более подробное представление архитектуры приложения ASP.NET Core, построенного с соблюдением этих рекомендаций.

ASP.NET Core architecture diagram following Clean Architecture

Рис. 5-9. Схема чистой архитектуры ASP.NET Core.

Поскольку ядро приложения не зависит от инфраструктуры, для этого слоя легко писать автоматические модульные тесты. На рис. 5-10 и 5-11 показано, как эти тесты вписываются в такую архитектуру.

UnitTestCore

Рис. 5-10. Изолированное модульное тестирование ядра приложения.

IntegrationTests

Рис. 5-11. Интеграционное тестирование реализаций инфраструктуры с внешними зависимостями.

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

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

ASP.NET Core Architecture 2

Рис. 5-12. Пример архитектуры приложения ASP.NET Core во время выполнения.

Упорядочение кода в рамках чистой архитектуры

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

Ядро приложения

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

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

Инфраструктура

Как правило, проект инфраструктуры включает реализацию доступа к данным. В типовом веб-приложении ASP.NET Core эта реализация включает Entity Framework (EF) DbContext, любые определенные объекты Migration EF Core, а также классы реализации доступа к данным. Наиболее распространенный подход к абстрагированию кода реализации доступа к данным заключается в использовании конструктивного шаблона репозитория.

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

Типы инфраструктуры
  • Типы EF Core (DbContext, Migration)
  • Типы реализации доступа к данным (репозитории)
  • Службы, связанные с инфраструктурой (например, FileLogger или SmtpNotifier)

Уровень пользовательского интерфейса

Слой пользовательского интерфейса в приложении MVC ASP.NET Core выступает в качестве точки входа для приложения. Этот проект должен ссылаться на слой ядра приложения, а его типы должны взаимодействовать с инфраструктурой строго через интерфейсы, определенные в ядре приложения. В слое пользовательского интерфейса не должны разрешаться прямое создание экземпляров для типов слоя инфраструктуры, а также их статические вызовы.

Типы слоев пользовательского интерфейса
  • Controllers
  • Настраиваемые фильтры
  • Пользовательское ПО промежуточного слоя.
  • Представления
  • ViewModels
  • Запуск

Класс Startup или файл Program.cs отвечает за настройку приложения и связывание типов реализации с интерфейсами. Расположение, где выполняется эта логика, называется корнем композиции приложения. Он обеспечивает правильное внедрение зависимостей во время выполнения.

Примечание.

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

Монолитные приложения и контейнеры

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

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

Figure 5-13

Вы можете включить в один контейнер несколько компонентов, библиотек или внутренних слоев, как показано на рис. 5-13. Такой монолитный шаблон может конфликтовать с принципом контейнера: "контейнер выполняет одно дело и в одном процессе".

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

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

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

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

Figure 5-14

Монолитные приложения в Microsoft Azure можно развертывать с использованием выделенных виртуальных машин для каждого экземпляра. С помощью масштабируемых наборов виртуальных машин Azure можно легко масштабировать виртуальные машины. Службы приложений Azure также могут выполнять монолитные приложения и легко масштабировать экземпляры, и вам не придется управлять виртуальными машинами. Службы приложений Azure также могут выполнять отдельные экземпляры контейнеров Docker, упрощая развертывание. С помощью Docker вы можете развернуть одну виртуальную машину на узле Docker и выполнять на ней несколько экземпляров. Для управления масштабированием можно использовать систему балансировки Azure, как показано на рис. 5-14.

Развертыванием на различных узлах можно управлять с помощью традиционных методов развертывания. Узлами Docker можно управлять с помощью вводимых вручную команд вида docker run или автоматизированно, например с помощью конвейеров непрерывной поставки (CD).

Развертывание монолитного приложения в контейнере

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

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

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

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

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

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

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

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

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

Гораздо более простой пример приложения eShopOnWeb поддерживает использование одного монолитного контейнера. Приложение включает одно веб-приложение с традиционными представлениями MVC, веб-API и Razor Pages. При необходимости можно запустить компонент администрирования приложения на основе Blazor, для которого также требуется запустить отдельный проект API.

Приложение может запускаться из корня решения с помощью команд docker-compose build и docker-compose up. Эта команда настраивает контейнер для веб-экземпляра с помощью Dockerfile из корневого каталога веб-проекта и выполняет контейнер в указанном порте. Вы можете скачать исходный код этого приложения из GitHub и запустить его в локальной системе. Даже такое монолитное приложение выигрывает от развертывания в контейнерной среде.

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

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

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

Поддержка Docker

Проект eShopOnWeb работает в .NET. Поэтому его можно запускать как в контейнерах Linux, так и в контейнерах Windows. Обратите внимание на то, что для развертывания Docker необходимо использовать тот же тип узла для SQL Server. Контейнеры на основе Linux требуют меньше ресурсов и более предпочтительны.

Вы можете использовать Visual Studio 2017, чтобы добавить поддержку Docker в существующее приложение, щелкнув проект в обозревателе решений правой кнопкой мыши и выбрав Добавить>Поддержка Docker. Таким образом вы добавите необходимые файлы и внесете изменения в проект для их использования. В текущем примере eShopOnWeb эти файлы уже есть.

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

version: '3'

services:
  eshopwebmvc:
    image: eshopwebmvc
    build:
      context: .
      dockerfile: src/Web/Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
    ports:
      - "5106:5106"

networks:
  default:
    external:
      name: nat

Файл docker-compose.yml ссылается на Dockerfile в проекте Web. С помощью Dockerfile можно указать, какой базовый контейнер будет использоваться и как приложение будет настроено на нем. DockerfileWeb:

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

COPY *.sln .
COPY . .
WORKDIR /app/src/Web
RUN dotnet restore

RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/src/Web/out ./

ENTRYPOINT ["dotnet", "Web.dll"]

Устранение неполадок с Docker

После запуска контейнерное приложение продолжает работать, пока его не остановят. Используйте команду docker ps, чтобы посмотреть, какие контейнеры выполняются. Вы можете остановить выполняющийся контейнер с помощью команды docker stop и идентификатора контейнера.

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

Если вы хотите добавить поддержку Docker в приложение с помощью Visual Studio, убедитесь, что Docker Desktop при этом запущен. Если при запуске мастера средство Docker Desktop не выполняется, мастер будет работать неправильно. Кроме того, мастер проверяет выбранные контейнеры, чтобы правильно реализовать поддержку Docker. Чтобы добавить поддержку контейнеров Windows, необходимо запускать мастер при запущенном инструменте Docker Desktop с настроенными контейнерами Windows. Чтобы добавить поддержку контейнеров Linux, запускайте мастер при запущенном инструменте Docker с настроенными контейнерами Linux.

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

  • Веб-queue-Worker: основные компоненты этой архитектуры — это веб-интерфейс, обслуживающий клиентские запросы, а также рабочий процесс, выполняющий ресурсоемкие задачи, длительные рабочие процессы или пакетные задания. Веб-интерфейс взаимодействует с рабочей ролью через очередь сообщений.
  • N-уровень: архитектура N-уровня делит приложение на логические слои и физические уровни.
  • Микрослужба: архитектура микрослужб состоит из коллекции небольших автономных служб. Каждая служба является самодостаточной и должна реализовывать возможности одной компании в ограниченном контексте.

Ссылки — общие архитектуры веб-приложений