Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Dica
Esse conteúdo é um trecho do eBook, Arquiteto de Aplicativos Web Modernos com ASP.NET Core e Azure, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.
"Se você acha que uma boa arquitetura é cara, experimente uma arquitetura ruim." - Brian Foote e Joseph Yoder
A maioria dos aplicativos .NET tradicionais são implantados como unidades individuais correspondentes a um executável ou a um único aplicativo Web em execução em um único appdomain do IIS. Essa abordagem é o modelo de implantação mais simples e atende muito bem a muitos aplicativos públicos internos e menores. No entanto, mesmo considerando essa única unidade de implantação, a maioria dos aplicativos empresariais não triviais se beneficiam de alguma separação lógica em várias camadas.
O que é um aplicativo monolítico?
Um aplicativo monolítico é totalmente independente, em termos de seu comportamento. Ele pode interagir com outros serviços ou armazenamentos de dados durante a execução de suas operações, mas o núcleo de seu comportamento é executado dentro de seu próprio processo e todo o aplicativo normalmente é implantado como uma única unidade. Se esse aplicativo precisar ser dimensionado horizontalmente, normalmente todo o aplicativo será duplicado em vários servidores ou máquinas virtuais.
Aplicativos tudo-em-um
O menor número possível de projetos para uma arquitetura de aplicativo é um. Nessa arquitetura, toda a lógica do aplicativo está contida em um único projeto, compilada em um único assembly e implantada como uma única unidade.
Um novo projeto do ASP.NET Core, criado no Visual Studio ou na linha de comando, inicia como um simples monolito "tudo-em-um". Ele contém todo o comportamento do aplicativo, incluindo a lógica de apresentação, negócios e acesso a dados. A Figura 5-1 mostra a estrutura de arquivos de um aplicativo de projeto único.
Figura 5-1. Um único projeto de aplicativo ASP.NET Core.
Em um único cenário de projeto, a separação de preocupações é obtida por meio do uso de pastas. O modelo padrão inclui pastas separadas para responsabilidades de padrão MVC de Modelos, Exibições e Controladores, bem como pastas adicionais para Dados e Serviços. Nessa disposição, os detalhes da apresentação devem ser limitados o máximo possível à pasta Exibições, e os detalhes de implementação de acesso a dados devem ser limitados às classes mantidas na pasta Dados. A lógica de negócios deve residir em serviços e classes dentro da pasta Modelos.
Embora simples, a solução monolítica de projeto único tem algumas desvantagens. À medida que o tamanho e a complexidade do projeto aumentarem, o número de arquivos e pastas continuará crescendo também. As preocupações de interface do usuário (modelos, exibições, controladores) residem em várias pastas, que não são agrupadas em ordem alfabética. Esse problema só fica pior quando construções adicionais no nível da interface do usuário, como Filtros ou ModelBinders, são adicionadas em suas próprias pastas. A lógica de negócios está dispersa entre as pastas Modelos e Serviços e não há nenhuma indicação clara de quais classes nas quais as pastas devem depender de quais outras. Essa falta de organização no nível do projeto frequentemente leva ao código spaghetti.
Para resolver esses problemas, os aplicativos geralmente evoluem para soluções de vários projetos, em que cada projeto é considerado em uma camada específica do aplicativo.
O que são camadas?
À medida que os aplicativos aumentam em complexidade, uma maneira de gerenciar essa complexidade é interromper o aplicativo de acordo com suas responsabilidades ou preocupações. Essa abordagem segue o princípio de separação de preocupações e pode ajudar a manter uma base de código crescente organizada para que os desenvolvedores possam encontrar facilmente onde determinada funcionalidade é implementada. No entanto, a arquitetura em camadas oferece várias vantagens além da organização de código.
Ao organizar o código em camadas, a funcionalidade comum de baixo nível pode ser reutilizada em toda a aplicação. Essa reutilização é benéfica porque significa que menos código precisa ser escrito e porque pode permitir que o aplicativo padronizar-se em uma única implementação, seguindo o princípio não repita você mesmo (DRY).
Com uma arquitetura em camadas, os aplicativos podem impor restrições nas quais as camadas podem se comunicar com outras camadas. Essa arquitetura ajuda a alcançar o encapsulamento. Quando uma camada é alterada ou substituída, somente as camadas que funcionam com ela devem ser afetadas. Limitando quais camadas dependem de quais outras camadas, o impacto das alterações pode ser atenuado para que uma única alteração não afete todo o aplicativo.
As camadas (e o encapsulamento) facilitam muito a substituição da funcionalidade dentro do aplicativo. Por exemplo, um aplicativo pode inicialmente usar seu próprio banco de dados do SQL Server para persistência, mas depois pode optar por usar uma estratégia de persistência baseada em nuvem ou uma por trás de uma API Web. Se o aplicativo tiver encapsulado corretamente sua implementação de persistência dentro de uma camada lógica, essa camada específica do SQL Server poderá ser substituída por uma nova implementando a mesma interface pública.
Além do potencial de trocar implementações em resposta a alterações futuras nos requisitos, as camadas de aplicativo também podem facilitar a troca de implementações para fins de teste. Em vez de precisar escrever testes que operem na camada de dados real ou na camada de interface do usuário do aplicativo, essas camadas podem ser substituídas no tempo de teste por implementações falsas que fornecem respostas conhecidas às solicitações. Essa abordagem normalmente torna os testes muito mais fáceis de gravar e muito mais rápidos de serem executados em comparação com a execução de testes em relação à infraestrutura real do aplicativo.
Camadas lógicas são uma técnica comum para melhorar a organização do código em aplicativos de software corporativo e há várias maneiras pelas quais o código pode ser organizado em camadas.
Observação
As camadas representam a separação lógica dentro do aplicativo. Caso a lógica do aplicativo seja distribuída fisicamente para servidores ou processos separados, esses destinos de implantação física separados são conhecidos como camadas. É possível e bastante comum ter um aplicativo N-Layer implantado em uma única camada.
Aplicativos de arquitetura "N-Layer" tradicionais
A organização mais comum da lógica do aplicativo em camadas é mostrada na Figura 5-2.
Figura 5-2. Camadas de aplicativo típicas.
Essas camadas são frequentemente abreviadas como interface do usuário, BLL (Camada lógica de negócios) e DAL (Camada de Acesso a Dados). Usando essa arquitetura, os usuários fazem solicitações por meio da camada de interface do usuário, que interage apenas com a BLL. A BLL, por sua vez, pode chamar o DAL para solicitações de acesso a dados. A camada de interface do usuário não deve fazer nenhuma solicitação diretamente ao DAL, nem deve interagir com a persistência diretamente por outros meios. Da mesma forma, a BLL só deve interagir com persistência por meio da DAL. Dessa forma, cada camada tem sua própria responsabilidade conhecida.
Uma desvantagem dessa abordagem tradicional de camadas é que as dependências de tempo de compilação são executadas de cima para baixo. Ou seja, a camada de interface do usuário depende da BLL, que depende do DAL. Isso significa que a BLL, que geralmente contém a lógica mais importante no aplicativo, depende dos detalhes de implementação de acesso a dados (e muitas vezes da existência de um banco de dados). Testar a lógica de negócios em tal arquitetura geralmente é difícil, exigindo um banco de dados de teste. O princípio de inversão de dependência pode ser usado para resolver esse problema, como você verá na próxima seção.
A Figura 5-3 mostra uma solução de exemplo, dividindo o aplicativo em três projetos por responsabilidade (ou camada).
Figura 5-3. Um aplicativo monolítico simples com três projetos.
Embora esse aplicativo use vários projetos para fins organizacionais, ele ainda é implantado como uma única unidade e seus clientes interagirão com ele como um único aplicativo Web. Isso permite um processo de implantação muito simples. A Figura 5-4 mostra como esse aplicativo pode ser hospedado usando o Azure.
Figura 5-4. Implantação simples do Aplicativo Web do Azure
À medida que as necessidades do aplicativo aumentam, soluções de implantação mais complexas e robustas podem ser necessárias. A Figura 5-5 mostra um exemplo de um plano de implantação mais complexo que dá suporte a recursos adicionais.
Figura 5-5. Implantando um aplicativo Web em um Serviço de Aplicativo do Azure
Internamente, a organização deste projeto em vários projetos com base na responsabilidade melhora a manutenção do aplicativo.
Essa unidade pode ser escalada verticalmente ou horizontalmente para aproveitar a escalabilidade sob demanda baseada em nuvem. Escalar verticalmente significa adicionar CPU, memória, espaço em disco ou outros recursos adicionais aos servidores que hospedam seu aplicativo. Escalar horizontalmente significa adicionar instâncias adicionais desses servidores, sejam servidores físicos, máquinas virtuais ou contêineres. Quando seu aplicativo é hospedado em várias instâncias, um balanceador de carga é usado para atribuir solicitações a instâncias de aplicativo individuais.
A abordagem mais simples para dimensionar um aplicativo Web no Azure é configurar o dimensionamento manualmente no Plano do Serviço de Aplicativo do aplicativo. A Figura 5-6 mostra a tela de painel apropriada do Azure para configurar quantas instâncias estão atendendo um aplicativo.
Figura 5-6. Dimensionamento do Plano do Serviço de Aplicativo no Azure.
Arquitetura limpa
Os aplicativos que seguem o Princípio da Inversão de Dependência, bem como os princípios de DDD (design de Domain-Driven) tendem a chegar a uma arquitetura semelhante. Essa arquitetura passou por muitos nomes ao longo dos anos. Um dos primeiros nomes foi Arquitetura Hexagonal, seguido por Portas e Adaptadores. Mais recentemente, ele foi citado como arquitetura onion ou arquitetura limpa. O último nome, Arquitetura Limpa, é usado como o nome dessa arquitetura neste e-book.
O aplicativo de referência eShopOnWeb usa a abordagem de Arquitetura Limpa na organização de seu código em projetos. Você pode encontrar um modelo de solução que pode usar como ponto de partida para suas próprias soluções do ASP.NET Core no repositório GitHub ardalis/cleanarchitecture ou instalando o modelo do NuGet.
A arquitetura limpa coloca a lógica de negócios e o modelo de aplicativo no centro do aplicativo. Em vez de ter lógica de negócios dependendo do acesso a dados ou outras preocupações de infraestrutura, essa dependência é invertida: os detalhes de infraestrutura e implementação dependem do Application Core. Essa funcionalidade é obtida definindo abstrações, ou interfaces, no Application Core, que são então implementadas por tipos definidos na camada infraestrutura. Uma maneira comum de visualizar essa arquitetura é usar uma série de círculos concêntricos, semelhantes a uma cebola. A Figura 5-7 mostra um exemplo desse estilo de representação arquitetônica.
Figura 5-7. Arquitetura Limpa; exibição de cebola
Neste diagrama, as dependências fluem em direção ao círculo mais interno. O Núcleo da Aplicação recebe seu nome devido à sua posição no centro deste diagrama. E você pode ver no diagrama que o Application Core não tem dependências em outras camadas de aplicativo. As entidades e interfaces do aplicativo estão no centro. Logo fora, mas ainda no Application Core, estão os serviços de domínio, que normalmente implementam interfaces definidas no círculo interno. Fora do Application Core, tanto a interface do usuário quanto as camadas de infraestrutura dependem do Application Core, mas não entre si (necessariamente).
A Figura 5-8 mostra um diagrama de camada horizontal mais tradicional que reflete melhor a dependência entre a interface do usuário e outras camadas.
Figura 5-8. Arquitetura limpa; exibição de camada horizontal
Observe que as setas sólidas representam dependências de tempo de compilação, enquanto a seta tracejada representa uma dependência somente de runtime. Com a arquitetura limpa, a camada de interface do usuário funciona com interfaces definidas no Application Core em tempo de compilação e, idealmente, não deve saber sobre os tipos de implementação definidos na camada infraestrutura. No entanto, em tempo de execução, esses tipos de implementação são necessários para que o aplicativo seja executado, portanto, eles precisam estar presentes e conectados às interfaces do Application Core por meio da injeção de dependência.
A Figura 5-9 mostra uma exibição mais detalhada da arquitetura de um aplicativo ASP.NET Core quando criada seguindo essas recomendações.
Figura 5-9. diagrama de arquitetura do ASP.NET Core seguindo a Arquitetura Limpa.
Como o Application Core não depende da Infraestrutura, é muito fácil gravar testes de unidade automatizados para essa camada. Os números 5-10 e 5-11 mostram como os testes se encaixam nessa arquitetura.
Figura 5-10. Realizando o teste de unidade do Núcleo do Aplicativo em isolamento.
Figura 5-11. Testes de integração de implementações de infraestrutura com dependências externas.
Como a camada de interface do usuário não tem nenhuma dependência direta dos tipos definidos no projeto de Infraestrutura, também é muito fácil trocar implementações, seja para facilitar o teste ou em resposta à alteração dos requisitos do aplicativo. O uso interno do ASP.NET Core e o suporte à injeção de dependência torna essa arquitetura a maneira mais apropriada de estruturar aplicativos monolíticos não triviais.
Para aplicativos monolíticos, os projetos application core, infraestrutura e interface do usuário são todos executados como um único aplicativo. A arquitetura do aplicativo de runtime pode ser semelhante à Figura 5-12.
Figura 5-12. Um exemplo de arquitetura de runtime de um aplicativo ASP.NET Core.
Organizando código na Arquitetura Limpa
Em uma solução de Arquitetura Limpa, cada projeto tem responsabilidades claras. Dessa forma, determinados tipos pertencem a cada projeto e você frequentemente encontrará pastas correspondentes a esses tipos no projeto apropriado.
Núcleo do Aplicativo
O Application Core contém o modelo de negócios, que inclui entidades, serviços e interfaces. Essas interfaces incluem abstrações para operações que serão executadas usando a Infraestrutura, como acesso a dados, acesso ao sistema de arquivos, chamadas de rede etc. Às vezes, os serviços ou interfaces definidos nessa camada precisarão trabalhar com tipos que não têm dependências na interface do usuário ou na infraestrutura. Eles podem ser definidos como DTOs (Objetos de Transferência de Dados) simples.
Tipos do Application Core
- Entidades (classes de modelo de negócios que são mantidas)
- Agregações (grupos de entidades)
- Interfaces
- Serviços de Domínio
- Especificações
- Exceções personalizadas e cláusulas de proteção
- Eventos e manipuladores de domínio
Infra-estrutura
O projeto de infraestrutura normalmente inclui implementações de acesso a dados. Em um aplicativo Web ASP.NET Core típico, essas implementações incluem o DbContext do EF (Entity Framework), todos os objetos EF Core Migration
que foram definidos e classes de implementação de acesso a dados. A maneira mais comum de abstrair o código de implementação de acesso a dados é por meio do uso do padrão de design do Repositório.
Além das implementações de acesso a dados, o projeto infraestrutura deve conter implementações de serviços que devem interagir com preocupações de infraestrutura. Esses serviços devem implementar interfaces definidas no Application Core e, portanto, a Infraestrutura deve ter uma referência ao projeto do Application Core.
Tipos de infraestrutura
- Tipos de EF Core (
DbContext
,Migration
) - Tipos de implementação de acesso a dados (repositórios)
- Serviços específicos da infraestrutura (por exemplo,
FileLogger
ouSmtpNotifier
)
Camada de interface do usuário
A camada de interface do usuário em um aplicativo ASP.NET Core MVC é o ponto de entrada do aplicativo. Esse projeto deve fazer referência ao projeto do Application Core e seus tipos devem interagir com a infraestrutura estritamente por meio de interfaces definidas no Application Core. Nenhuma instanciação direta ou chamadas estáticas para os tipos da camada de infraestrutura devem ser permitidas na camada de interface do usuário.
Tipos de camada de interface do usuário
- Controladores
- Filtros personalizados
- Middleware personalizado
- Visões
- ViewModels
- Inicialização
A Startup
classe ou Program.cs arquivo é responsável por configurar o aplicativo e por conectar tipos de implementação a interfaces. O local onde essa lógica é executada é conhecido como a raiz de composição do aplicativo e é o que permite que a injeção de dependência funcione corretamente em tempo de execução.
Observação
Para configurar a injeção de dependência durante a inicialização do aplicativo, o projeto da camada de interface do usuário pode precisar referenciar o projeto de infraestrutura. Essa dependência pode ser eliminada, mais facilmente usando um contêiner DI personalizado que tem suporte interno para tipos de carregamento de assemblies. Para fins deste exemplo, a abordagem mais simples é permitir que o projeto de interface do usuário faça referência ao projeto de infraestrutura (mas os desenvolvedores devem limitar as referências reais a tipos no projeto de Infraestrutura à raiz de composição do aplicativo).
Aplicativos e contêineres monolíticos
Você pode criar um aplicativo Web ou serviço baseado em implantação monolítica e único e implantá-lo como um contêiner. No aplicativo, ele pode não ser monolítico, mas organizado em várias bibliotecas, componentes ou camadas. Externamente, é um único contêiner com um único processo, um único aplicativo Web ou um único serviço.
Para gerenciar esse modelo, você implanta um único contêiner para representar o aplicativo. Para dimensionar, basta adicionar mais cópias com um balanceador de carga na frente. A simplicidade vem do gerenciamento de uma única implantação em um único contêiner ou VM.
Você pode incluir vários componentes/bibliotecas ou camadas internas em cada contêiner, conforme ilustrado na Figura 5-13. Mas, seguindo o princípio de contêiner de "um contêiner executa uma ação e faz isso em um processo", o padrão monolítico pode gerar um conflito.
A desvantagem dessa abordagem vem se/quando o aplicativo cresce, exigindo que ele seja dimensionado. Se todo o aplicativo escalar, isso não será realmente um problema. No entanto, na maioria dos casos, algumas partes do aplicativo são os pontos de estrangulamento que exigem dimensionamento, enquanto outros componentes são menos usados.
Usando o exemplo típico de eCommerce, o que você provavelmente precisa dimensionar é o componente de informações do produto. Uma quantidade muito maior de clientes procura produtos em vez de comprá-los. Mais clientes usam sua cesta do que usam o sistema de pagamento. Menos clientes adicionam comentários ou veem seu histórico de compras. E você provavelmente tem apenas um punhado de funcionários, em uma única região, que precisam gerenciar o conteúdo e as campanhas de marketing. Ao aplicar escala ao projeto monolítico, todo o código é implantado várias vezes.
Além do problema de "dimensionar tudo", as alterações em um único componente exigem o reteste completo de todo o aplicativo e uma reimplantação completa de todas as instâncias.
A abordagem monolítica é comum e muitas organizações estão desenvolvendo com essa abordagem arquitetônica. Muitos estão tendo bons resultados o suficiente, enquanto outros estão atingindo limites. Muitos projetaram seus aplicativos nesse modelo, pois as ferramentas e a infraestrutura eram muito difíceis de criar arquiteturas orientadas a serviço (SOA) e não viam a necessidade até que o aplicativo crescesse. Se você descobrir que está atingindo os limites da abordagem monolítica, dividir o aplicativo para permitir que ele aproveite melhor os contêineres e os microsserviços pode ser a próxima etapa lógica.
A implantação de aplicativos monolíticos no Microsoft Azure pode ser obtida usando VMs dedicadas para cada instância. Usando conjuntos de dimensionamento de máquinas virtuais do Azure, você pode dimensionar facilmente as VMs. Os Serviços de Aplicativo do Azure podem executar aplicativos monolíticos e dimensionar facilmente instâncias sem precisar gerenciar as VMs. Os Serviços de Aplicativo do Azure também podem executar instâncias individuais de contêineres do Docker, simplificando a implantação. Usando o Docker, você pode implantar uma única VM como um host do Docker e executar várias instâncias. Usando o balanceador do Azure, conforme mostrado na Figura 5-14, você pode gerenciar o dimensionamento.
A implantação para os vários hosts pode ser gerenciada com técnicas de implantação tradicionais. Os hosts do Docker podem ser gerenciados com comandos como docker run executados manualmente ou por meio de automação, como pipelines de Entrega Contínua (CD).
Aplicativo monolítico implementado como um contêiner
Há benefícios de usar contêineres para gerenciar implantações de aplicativos monolíticos. Dimensionar as instâncias de contêineres é muito mais rápido e fácil do que implantar VMs adicionais. Mesmo ao usar conjuntos de dimensionamento de máquinas virtuais para dimensionar VMs, eles levam tempo para serem criados. Quando implantada como instâncias de aplicativo, a configuração do aplicativo é gerenciada como parte da VM.
Implantar atualizações como imagens do Docker é muito mais rápido e eficiente para a rede. As Imagens do Docker costumam ser iniciadas em segundos, o que agiliza as distribuições. Derrubar uma instância do Docker é tão fácil quanto emitir um docker stop
comando, normalmente concluindo em menos de um segundo.
Como os contêineres são inerentemente imutáveis por design, você nunca precisa se preocupar com VMs corrompidas, enquanto os scripts de atualização podem esquecer de considerar alguma configuração ou arquivo específico deixado no disco.
Você pode usar contêineres do Docker para uma implantação monolítica de aplicativos Web mais simples. Essa abordagem melhora os pipelines de integração contínua e de implantação contínua e ajuda a obter êxito na implantação de produção. Chega de "Funciona no meu computador, por que não funciona em produção?"
Uma arquitetura baseada em microsserviços tem muitos benefícios, mas esses benefícios têm um custo de maior complexidade. Em alguns casos, os custos superam os benefícios, portanto, um aplicativo de implantação monolítico em execução em um único contêiner ou em apenas alguns contêineres é uma opção melhor.
Um aplicativo monolítico pode não ser facilmente decomponível em microsserviços bem separados. Os microsserviços devem funcionar independentemente uns dos outros para fornecer um aplicativo mais resiliente. Se você não puder fornecer fatias de recursos independentes do aplicativo, separá-lo só adicionará complexidade.
Talvez um aplicativo ainda não precise dimensionar os recursos de forma independente. Muitos aplicativos, quando precisam ser dimensionados além de uma única instância, podem fazê-lo por meio do processo relativamente simples de clonagem de toda essa instância. O trabalho adicional para separar o aplicativo em serviços discretos oferece um benefício mínimo quando o dimensionamento de instâncias completas do aplicativo é simples e econômico.
No início do desenvolvimento de um aplicativo, talvez você não tenha uma ideia clara de onde estão os limites funcionais naturais. À medida que você desenvolve um produto mínimo viável, a separação natural pode ainda não ter surgido. Algumas dessas condições podem ser temporárias. Você pode começar criando um aplicativo monolítico e, posteriormente, separar alguns recursos a serem desenvolvidos e implantados como microsserviços. Outras condições podem ser essenciais para o espaço problemático do aplicativo, o que significa que o aplicativo pode nunca ser dividido em vários microsserviços.
Separar um aplicativo em muitos processos discretos também introduz sobrecarga. Existe mais complexidade na separação de funcionalidades em diferentes processos. Os protocolos de comunicação tornam-se mais complexos. Em vez de chamadas de método, você deve usar a comunicação assíncrona entre serviços. Conforme você passa para uma arquitetura de microsserviços, é necessário adicionar muitos dos blocos de construção implementados na versão de microsserviços do aplicativo eShopOnContainers: manipulação de barramento de eventos, resiliência e repetições de mensagens, consistência eventual e muito mais.
O aplicativo de referência eShopOnWeb muito simples dá suporte ao uso de contêiner monolítico único. O aplicativo inclui uma aplicação web que abrange exibições MVC tradicionais, APIs Web e Páginas Razor. Opcionalmente, você pode executar o componente de administração baseado em Blazor do aplicativo, que exige que um projeto de API separado também seja executado.
O aplicativo pode ser iniciado a partir da raiz da solução usando os comandos docker-compose build
e docker-compose up
. Esse comando configura um contêiner para a instância da Web, usando o Dockerfile
encontrado na raiz do projeto Web e executa o contêiner em uma porta especificada. Você pode baixar a origem deste aplicativo no GitHub e executá-lo localmente. Até mesmo esse aplicativo monolítico se beneficia de ser implantado em um ambiente de contêiner.
Por um lado, a implantação em contêineres significa que cada instância do aplicativo é executada no mesmo ambiente. Essa abordagem inclui o ambiente do desenvolvedor em que ocorrem testes e desenvolvimento antecipados. A equipe de desenvolvimento pode executar o aplicativo em um ambiente em contêineres que corresponda ao ambiente de produção.
Além disso, os aplicativos em contêineres são aumentados com um custo menor. O uso de um ambiente de contêiner permite maior compartilhamento de recursos do que os ambientes de VM tradicionais.
Por fim, o contêiner do aplicativo força uma separação entre a lógica de negócios e o servidor de armazenamento. Conforme o aplicativo é expandido, os vários contêineres dependerão de um único meio de armazenamento físico. Esse meio de armazenamento normalmente seria um servidor de alta disponibilidade executando um banco de dados do SQL Server.
Suporte ao Docker
O eShopOnWeb
projeto é executado no .NET. Portanto, ele pode ser executado em contêineres baseados em Linux ou windows. Observe que, para a implantação do Docker, você deseja usar o mesmo tipo de host para o SQL Server. Os contêineres baseados em Linux permitem um volume menor e são preferenciais.
Você pode usar o Visual Studio 2017 ou posterior para adicionar suporte do Docker a um aplicativo existente clicando com o botão direito do mouse em um projeto no Gerenciador de Soluções e escolhendo Adicionar>Suporte ao Docker. Esta etapa adiciona os arquivos necessários e modifica o projeto para usá-los. O exemplo atual eShopOnWeb
já tem esses arquivos prontos.
O arquivo no nível de solução docker-compose.yml
contém informações sobre quais imagens criar e quais contêineres iniciar. O arquivo permite que você use o docker-compose
comando para iniciar vários aplicativos ao mesmo tempo. Nesse caso, ele só está iniciando o projeto Web. Você também pode usá-lo para configurar dependências, como um contêiner de banco de dados separado.
version: '3'
services:
eshopwebmvc:
image: eshopwebmvc
build:
context: .
dockerfile: src/Web/Dockerfile
environment:
- ASPNETCORE_ENVIRONMENT=Development
ports:
- "5106:5106"
networks:
default:
external:
name: nat
O arquivo docker-compose.yml
faz referência ao Dockerfile
no projeto Web
. O Dockerfile
é usado para especificar qual contêiner base será usado e como o aplicativo será configurado nele. O Web
do Dockerfile
:
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"]
Solução de problemas do Docker
Depois de executar o aplicativo em contêineres, ele continuará a ser executado até que você o interrompa. Você pode exibir quais contêineres estão em execução com o docker ps
comando. Você pode interromper um contêiner em execução usando o docker stop
comando e especificando a ID do contêiner.
Observe que a execução de contêineres do Docker pode estar associada a portas que você pode tentar usar em seu ambiente de desenvolvimento. Se você tentar executar ou depurar um aplicativo usando a mesma porta que um contêiner do Docker em execução, receberá um erro informando que o servidor não pode se associar a essa porta. Mais uma vez, parar o contêiner deve resolver o problema.
Se você quiser adicionar suporte ao Docker ao seu aplicativo usando o Visual Studio, verifique se o Docker Desktop está em execução quando você fizer isso. O assistente não será executado corretamente se o Docker Desktop não estiver em execução quando você iniciar o assistente. Além disso, o assistente examina sua opção de contêiner atual para adicionar o suporte correto ao Docker. Se você quiser adicionar suporte para contêineres do Windows, será necessário executar o assistente enquanto você tem a Área de Trabalho do Docker em execução com contêineres do Windows configurados. Se você quiser adicionar suporte a contêineres do Linux, execute o assistente quando tiver o Docker em execução com contêineres do Linux já configurados.
Outros estilos de arquitetura de aplicativo Web
- Web-Queue-Worker: os principais componentes dessa arquitetura são um front-end da Web que atende a solicitações de cliente e um trabalho que executa tarefas com uso intensivo de recursos, fluxos de trabalho de execução longa ou trabalhos em lotes. O front-end da Web se comunica com o trabalhador por meio de uma fila de mensagens.
- N camadas: uma arquitetura de N camadas divide um aplicativo em camadas lógicas e camadas físicas.
- Microsserviço: uma arquitetura de microsserviços consiste em uma coleção de serviços pequenos e autônomos. Cada serviço é independente e deve implementar uma única funcionalidade comercial em um contexto limitado.
Referências – arquiteturas da Web comuns
-
A Arquitetura Limpa
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html -
A Arquitetura de Cebola
https://jeffreypalermo.com/blog/the-onion-architecture-part-1/ -
O padrão do repositório
https://deviq.com/repository-pattern/ -
Modelo de solução de arquitetura limpa
https://github.com/ardalis/cleanarchitecture -
Arquitetura de Microsserviços e-book
https://aka.ms/MicroservicesEbook -
DDD (DesignDomain-Driven)
https://learn.microsoft.com/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/