Dela via


Vanliga webbprogramarkitekturer

Dricks

Det här innehållet är ett utdrag från eBook, Architect Modern Web Applications med ASP.NET Core och Azure, som finns på .NET Docs eller som en kostnadsfri nedladdningsbar PDF som kan läsas offline.

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

"Om du tycker att bra arkitektur är dyrt kan du prova dålig arkitektur." - Brian Foote och Joseph Yoder

De flesta traditionella .NET-program distribueras som enskilda enheter som motsvarar en körbar eller en enda webbapp som körs i en enda IIS-appdomän. Den här metoden är den enklaste distributionsmodellen och fungerar mycket bra för många interna och mindre offentliga program. Men även med tanke på den här enskilda distributionsenheten drar de flesta icke-triviala affärsprogram nytta av en logisk uppdelning i flera lager.

Vad är ett monolitiskt program?

Ett monolitiskt program är ett program som är helt fristående, när det gäller dess beteende. Det kan interagera med andra tjänster eller datalager under driften, men kärnan i dess beteende körs i sin egen process och hela programmet distribueras vanligtvis som en enda enhet. Om ett sådant program behöver skalas horisontellt dupliceras vanligtvis hela programmet över flera servrar eller virtuella datorer.

Allt-i-ett-program

Det minsta möjliga antalet projekt för en programarkitektur är ett. I den här arkitekturen finns hela logiken i programmet i ett enda projekt, kompileras till en enda sammansättning och distribueras som en enda enhet.

Ett nytt ASP.NET Core-projekt, oavsett om det skapas i Visual Studio eller från kommandoraden, börjar som en enkel "allt-i-ett"-monolit. Den innehåller allt beteende för programmet, inklusive presentations-, affärs- och dataåtkomstlogik. Bild 5–1 visar filstrukturen för en enskild projektapp.

A single project ASP.NET Core app

Bild 5-1. Ett enda projekt ASP.NET Core-appen.

I ett enda projektscenario uppnås separation av problem med hjälp av mappar. Standardmallen innehåller separata mappar för MVC-mönsteransvar för modeller, vyer och kontrollanter samt ytterligare mappar för data och tjänster. I det här arrangemanget bör presentationsinformationen begränsas så mycket som möjligt till mappen Vyer, och information om implementering av dataåtkomst bör begränsas till klasser som lagras i mappen Data. Affärslogik bör finnas i tjänster och klasser i mappen Modeller.

Även om det är enkelt har den monolitiska lösningen med ett projekt vissa nackdelar. I takt med att projektets storlek och komplexitet växer fortsätter även antalet filer och mappar att växa. Användargränssnittsproblem (modeller, vyer, kontrollanter) finns i flera mappar, som inte grupperas alfabetiskt. Det här problemet förvärras bara när ytterligare konstruktioner på användargränssnittsnivå, till exempel Filter eller ModelBinders, läggs till i sina egna mappar. Affärslogik är utspridda mellan mapparna Modeller och tjänster och det finns ingen tydlig indikation på vilka klasser i vilka mappar som ska vara beroende av vilka andra. Denna brist på organisation på projektnivå leder ofta till spaghettikod.

För att lösa dessa problem utvecklas program ofta till lösningar för flera projekt, där varje projekt anses finnas i ett visst lager i programmet.

Vad är lager?

I takt med att programmen blir komplexa är ett sätt att hantera den komplexiteten att dela upp programmet enligt dess ansvarsområden eller problem. Den här metoden följer principen om uppdelning av problem och kan hjälpa till att hålla en växande kodbas organiserad så att utvecklare enkelt kan hitta var vissa funktioner implementeras. Skiktad arkitektur erbjuder dock ett antal fördelar utöver bara kodorganisation.

Genom att ordna kod i lager kan vanliga funktioner på låg nivå återanvändas i hela programmet. Den här återanvändningen är fördelaktig eftersom det innebär att mindre kod måste skrivas och eftersom det kan göra det möjligt för programmet att standardisera på en enda implementering, enligt principen upprepa inte dig själv (DRY).

Med en flerskiktad arkitektur kan program tillämpa begränsningar för vilka skikt som kan kommunicera med andra lager. Den här arkitekturen hjälper till att uppnå inkapsling. När ett lager ändras eller ersätts ska endast de lager som fungerar med det påverkas. Genom att begränsa vilka skikt som är beroende av vilka andra skikt, kan effekten av ändringar minimeras så att en enskild ändring inte påverkar hela programmet.

Lager (och inkapsling) gör det mycket enklare att ersätta funktioner i programmet. Ett program kan till exempel till en början använda sin egen SQL Server-databas för beständighet, men senare kan välja att använda en molnbaserad beständighetsstrategi eller en bakom ett webb-API. Om programmet korrekt har kapslat in sin beständighetsimplementering i ett logiskt lager kan det SQL Server-specifika lagret ersättas av ett nytt som implementerar samma offentliga gränssnitt.

Förutom möjligheten att byta ut implementeringar som svar på framtida ändringar i kraven kan programskikt också göra det enklare att byta ut implementeringar i testsyfte. I stället för att behöva skriva tester som fungerar mot det verkliga dataskiktet eller UI-lagret i programmet, kan dessa lager ersättas vid testtillfället med falska implementeringar som ger kända svar på begäranden. Den här metoden gör vanligtvis tester mycket enklare att skriva och mycket snabbare att köra jämfört med att köra tester mot programmets verkliga infrastruktur.

Logisk skiktning är en vanlig teknik för att förbättra organisationen av kod i program för företagsprogram, och det finns flera sätt på vilka kod kan ordnas i lager.

Kommentar

Lager representerar logisk separation i programmet. Om programlogik fysiskt distribueras till separata servrar eller processer kallas dessa separata fysiska distributionsmål för nivåer. Det är möjligt och ganska vanligt att ha ett N-Layer-program som distribueras till en enda nivå.

Traditionella "N-Layer"-arkitekturprogram

Den vanligaste organisationen av programlogik i lager visas i bild 5-2.

Typical application layers

Bild 5-2. Typiska programlager.

Dessa lager förkortas ofta som UI, BLL (Business Logic Layer) och DAL (Data Access Layer). Med den här arkitekturen gör användarna begäranden via användargränssnittsskiktet, som endast interagerar med BLL:n. BLL kan i sin tur anropa DAL för dataåtkomstbegäranden. Användargränssnittsskiktet bör inte göra några förfrågningar till DAL direkt och bör inte heller interagera med beständighet direkt på annat sätt. På samma sätt bör BLL endast interagera med beständighet genom att gå igenom DAL. På så sätt har varje lager sitt eget välkända ansvar.

En nackdel med den här traditionella skiktningsmetoden är att kompileringstidsberoenden körs uppifrån och ned. UI-lagret beror alltså på BLL, som är beroende av DAL. Det innebär att BLL,som vanligtvis innehåller den viktigaste logiken i programmet, är beroende av information om implementering av dataåtkomst (och ofta på förekomsten av en databas). Det är ofta svårt att testa affärslogik i en sådan arkitektur, vilket kräver en testdatabas. Principen för beroendeinversion kan användas för att åtgärda det här problemet, som du ser i nästa avsnitt.

Bild 5–3 visar en exempellösning som delar upp programmet i tre projekt efter ansvar (eller lager).

A simple monolithic application with three projects

Bild 5-3. Ett enkelt monolitiskt program med tre projekt.

Även om det här programmet använder flera projekt i organisationssyfte distribueras det fortfarande som en enda enhet och dess klienter interagerar med det som en enda webbapp. Detta möjliggör en mycket enkel distributionsprocess. Bild 5–4 visar hur en sådan app kan hanteras med Hjälp av Azure.

Simple deployment of Azure Web App

Bild 5-4. Enkel distribution av Azure Web App

När programbehoven växer kan det krävas mer komplexa och robusta distributionslösningar. Bild 5–5 visar ett exempel på en mer komplex distributionsplan som stöder ytterligare funktioner.

Deploying a web app to an Azure App Service

Bild 5-5. Distribuera en webbapp till en Azure App Service

Internt förbättrar projektets organisation i flera projekt baserat på ansvar programmets underhållsmöjligheter.

Den här enheten kan skalas upp eller ut för att dra nytta av molnbaserad skalbarhet på begäran. Att skala upp innebär att lägga till ytterligare PROCESSOR, minne, diskutrymme eller andra resurser till de servrar som är värdar för din app. Utskalning innebär att lägga till ytterligare instanser av sådana servrar, oavsett om det är fysiska servrar, virtuella datorer eller containrar. När din app finns i flera instanser används en lastbalanserare för att tilldela begäranden till enskilda appinstanser.

Den enklaste metoden för att skala ett webbprogram i Azure är att konfigurera skalning manuellt i programmets App Service-plan. Bild 5–6 visar lämplig Azure-instrumentpanelsskärm för att konfigurera hur många instanser som betjänar en app.

App Service Plan scaling in Azure

Bild 5-6. Skalning av App Service-plan i Azure.

Ren arkitektur

Program som följer principen för beroendeinversion samt principerna för domändriven design (DDD) tenderar att komma fram till en liknande arkitektur. Den här arkitekturen har gått under många namn genom åren. Ett av förnamnen var Hexagonal Architecture, följt av Ports-and-Adapters. På senare tid har den nämnts som Lökarkitektur eller Ren arkitektur. Det senare namnet, Clean Architecture, används som namn på den här arkitekturen i den här e-boken.

Referensprogrammet eShopOnWeb använder metoden Ren arkitektur för att organisera koden i projekt. Du hittar en lösningsmall som du kan använda som utgångspunkt för dina egna ASP.NET Core-lösningar på GitHub-lagringsplatsen ardalis/cleanarchitecture eller genom att installera mallen från NuGet.

Ren arkitektur placerar affärslogik- och programmodellen i mitten av programmet. I stället för att affärslogik är beroende av dataåtkomst eller andra infrastrukturproblem, inverteras det här beroendet: information om infrastruktur och implementering är beroende av Application Core. Den här funktionen uppnås genom att definiera abstraktioner eller gränssnitt i Application Core, som sedan implementeras av typer som definieras i infrastrukturlagret. Ett vanligt sätt att visualisera den här arkitekturen är att använda en serie koncentriska cirklar som liknar en lök. Bild 5–7 visar ett exempel på den här arkitekturrepresentationen.

Clean Architecture; onion view

Bild 5-7. Ren arkitektur; lökvy

I det här diagrammet flödar beroenden mot den innersta cirkeln. Application Core tar sitt namn från sin position i kärnan av det här diagrammet. Och du kan se i diagrammet att Application Core inte har några beroenden för andra programlager. Programmets entiteter och gränssnitt är i centrum. Precis utanför, men fortfarande i Application Core, finns domäntjänster, som vanligtvis implementerar gränssnitt som definierats i den inre cirkeln. Utanför Application Core är både användargränssnittet och infrastrukturlagren beroende av Application Core, men inte på varandra (nödvändigtvis).

Bild 5–8 visar ett mer traditionellt vågrätt lagerdiagram som bättre återspeglar beroendet mellan användargränssnittet och andra lager.

Clean Architecture; horizontal layer view

Bild 5-8. Ren arkitektur; vågrät skiktvy

Observera att de fasta pilarna representerar kompileringstidsberoenden, medan den streckade pilen representerar ett körningsberoende. Med den rena arkitekturen fungerar användargränssnittslagret med gränssnitt som definierats i Application Core vid kompileringstid och bör helst inte känna till de implementeringstyper som definierats i infrastrukturlagret. Vid körning krävs dock dessa implementeringstyper för att appen ska kunna köras, så de måste finnas och kopplas upp till Application Core-gränssnitten via beroendeinmatning.

Bild 5–9 visar en mer detaljerad vy över arkitekturen för ett ASP.NET Core-program när det skapas enligt dessa rekommendationer.

ASP.NET Core architecture diagram following Clean Architecture

Bild 5-9. ASP.NET Core-arkitekturdiagram efter Ren arkitektur.

Eftersom Application Core inte är beroende av infrastruktur är det mycket enkelt att skriva automatiserade enhetstester för det här lagret. Figurerna 5-10 och 5-11 visar hur tester passar in i den här arkitekturen.

UnitTestCore

Bild 5-10. Enhetstestning av Application Core isolerat.

IntegrationTests

Bild 5-11. Integreringstestning Infrastrukturimplementeringar med externa beroenden.

Eftersom UI-lagret inte har något direkt beroende av typer som definierats i infrastrukturprojektet är det också mycket enkelt att växla ut implementeringar, antingen för att underlätta testning eller som svar på ändrade programkrav. ASP.NET Cores inbyggda användning av och stöd för beroendeinmatning gör den här arkitekturen till det lämpligaste sättet att strukturera icke-triviala monolitiska program.

För monolitiska program körs alla Application Core-, Infrastruktur- och UI-projekt som ett enda program. Programarkitekturen för körning kan se ut ungefär som bild 5–12.

ASP.NET Core Architecture 2

Bild 5-12. Ett exempel ASP.NET Core-appens körningsarkitektur.

Organisera kod i ren arkitektur

I en lösning för ren arkitektur har varje projekt tydliga ansvarsområden. Därför hör vissa typer hemma i varje projekt och du hittar ofta mappar som motsvarar dessa typer i lämpligt projekt.

Application Core

Application Core innehåller affärsmodellen, som innehåller entiteter, tjänster och gränssnitt. Dessa gränssnitt omfattar abstraktioner för åtgärder som ska utföras med hjälp av infrastruktur, till exempel dataåtkomst, filsystemåtkomst, nätverksanrop osv. Ibland måste tjänster eller gränssnitt som definieras på det här lagret fungera med icke-entitetstyper som inte har några beroenden i användargränssnittet eller infrastrukturen. Dessa kan definieras som enkla dataöverföringsobjekt (DTU:er).

Application Core-typer
  • Entiteter (affärsmodellsklasser som är beständiga)
  • Aggregeringar (grupper av entiteter)
  • Gränssnitt
  • Domain Services
  • Specifikationer
  • Anpassade undantag och Guard-satser
  • Domänhändelser och -hanterare

Infrastruktur

Infrastrukturprojektet innehåller vanligtvis implementeringar av dataåtkomst. I ett typiskt ASP.NET Core-webbprogram omfattar dessa implementeringar Entity Framework (EF) DbContext, alla EF Core-objekt Migration som har definierats och implementeringsklasser för dataåtkomst. Det vanligaste sättet att abstrahera implementeringskod för dataåtkomst är att använda designmönstret För lagringsplats.

Förutom implementeringar av dataåtkomst bör infrastrukturprojektet innehålla implementeringar av tjänster som måste interagera med infrastrukturproblem. Dessa tjänster bör implementera gränssnitt som definierats i Application Core, så infrastruktur bör ha en referens till Application Core-projektet.

Infrastrukturtyper
  • EF Core-typer (DbContext, Migration)
  • Implementeringstyper för dataåtkomst (lagringsplatser)
  • Infrastrukturspecifika tjänster (till exempel FileLogger eller SmtpNotifier)

UI-lager

Användargränssnittsskiktet i ett ASP.NET Core MVC-program är startpunkten för programmet. Det här projektet bör referera till Application Core-projektet och dess typer bör interagera med infrastrukturen strikt via gränssnitt som definierats i Application Core. Ingen direkt instansiering av eller statiska anrop till infrastrukturlagertyperna ska tillåtas i användargränssnittslagret.

UI-lagertyper
  • Kontrollanter
  • Anpassade filter
  • Anpassat mellanprogram
  • Vyer
  • ViewModels
  • Start

Klassen Startup eller Program.cs-filen ansvarar för att konfigurera programmet och för att koppla implementeringstyper till gränssnitt. Platsen där den här logiken utförs kallas appens sammansättningsrot och är det som gör att beroendeinmatningen kan fungera korrekt vid körning.

Kommentar

För att kunna koppla in beroendeinmatningen under appstarten kan UI-lagerprojektet behöva referera till infrastrukturprojektet. Det här beroendet kan elimineras, enklast genom att använda en anpassad DI-container som har inbyggt stöd för inläsning av typer från sammansättningar. I det här exemplet är den enklaste metoden att tillåta att UI-projektet refererar till infrastrukturprojektet (men utvecklare bör begränsa faktiska referenser till typer i infrastrukturprojektet till appens sammansättningsrot).

Monolitiska program och containrar

Du kan skapa en enda och monolitisk distributionsbaserad webbapp eller tjänst och distribuera den som en container. I programmet kanske det inte är monolitiskt men indelat i flera bibliotek, komponenter eller lager. Externt är det en enda container med en enda process, ett enda webbprogram eller en enda tjänst.

För att hantera den här modellen distribuerar du en enda container som representerar programmet. Om du vill skala lägger du bara till ytterligare kopior med en lastbalanserare framför. Enkelheten kommer från att hantera en enskild distribution i en enda container eller virtuell dator.

Figure 5-13

Du kan inkludera flera komponenter/bibliotek eller interna lager i varje container, enligt bild 5–13. Men om du följer containerprincipen "en container gör en sak och gör det i en process" kan det monolitiska mönstret vara en konflikt.

Nackdelen med den här metoden är om/när programmet växer, vilket kräver att det ska skalas. Om hela programmet skalas är det egentligen inget problem. I de flesta fall är dock några delar av programmet de kvävningspunkter som kräver skalning, medan andra komponenter används mindre.

Med det typiska e-handelsexemplet behöver du förmodligen skala produktinformationskomponenten. Många fler kunder bläddrar bland produkter än köper dem. Fler kunder använder sin korg än att använda betalningspipelinen. Färre kunder lägger till kommentarer eller visar sin inköpshistorik. Och du har förmodligen bara en handfull anställda, i en enda region, som behöver hantera innehåll och marknadsföringskampanjer. Genom att skala den monolitiska designen distribueras all kod flera gånger.

Förutom "skala allt"-problemet kräver ändringar av en enskild komponent fullständig omtestning av hela programmet och en fullständig omdistribution av alla instanser.

Den monolitiska metoden är vanlig och många organisationer utvecklar med den här arkitekturmetoden. Många har tillräckligt bra resultat, medan andra når gränser. Många utformade sina program i den här modellen eftersom verktygen och infrastrukturen var för svåra att bygga tjänstorienterade arkitekturer (SOA) och de inte såg behovet förrän appen växte. Om du upptäcker att du når gränserna för den monolitiska metoden kan det vara nästa logiska steg att dela upp appen så att den bättre kan utnyttja containrar och mikrotjänster.

Figure 5-14

Distribution av monolitiska program i Microsoft Azure kan uppnås med hjälp av dedikerade virtuella datorer för varje instans. Med skalningsuppsättningar för virtuella Azure-datorer kan du enkelt skala de virtuella datorerna. Azure App Services kan köra monolitiska program och enkelt skala instanser utan att behöva hantera de virtuella datorerna. Azure App Services kan även köra enskilda instanser av Docker-containrar, vilket förenklar distributionen. Med Docker kan du distribuera en enskild virtuell dator som Docker-värd och köra flera instanser. Med Hjälp av Azure Balancer, som du ser i bild 5–14, kan du hantera skalning.

Distributionen till de olika värdarna kan hanteras med traditionella distributionstekniker. Docker-värdarna kan hanteras med kommandon som docker-körning som utförs manuellt eller via automatisering, till exempel CD-pipelines (Continuous Delivery).

Monolitiskt program som distribueras som en container

Det finns fördelar med att använda containrar för att hantera monolitiska programdistributioner. Det är mycket snabbare och enklare att skala instanserna av containrar än att distribuera ytterligare virtuella datorer. Även när du använder vm-skalningsuppsättningar för att skala virtuella datorer tar det tid att skapa dem. När den distribueras som appinstanser hanteras appens konfiguration som en del av den virtuella datorn.

Att distribuera uppdateringar som Docker-avbildningar är mycket snabbare och nätverkseffektivt. Docker-avbildningar startar vanligtvis på några sekunder, vilket påskyndar distributionen. Det är lika enkelt att riva en Docker-instans som att utfärda ett docker stop kommando, vanligtvis på mindre än en sekund.

Eftersom containrar är oföränderliga av design behöver du aldrig oroa dig för skadade virtuella datorer, medan uppdateringsskript kanske glömmer bort att ta hänsyn till en viss konfiguration eller fil som finns kvar på disken.

Du kan använda Docker-containrar för en monolitisk distribution av enklare webbprogram. Den här metoden förbättrar kontinuerlig integrering och kontinuerliga distributionspipelines och hjälper till att uppnå distribution till produktion. Inget mer "Det fungerar på min dator, varför fungerar det inte i produktion?"

En mikrotjänstbaserad arkitektur har många fördelar, men dessa fördelar kommer till en kostnad av ökad komplexitet. I vissa fall uppväger kostnaderna fördelarna, så ett monolitiskt distributionsprogram som körs i en enda container eller i bara några få containrar är ett bättre alternativ.

Ett monolitiskt program kanske inte är enkelt att dela upp i välavgränsade mikrotjänster. Mikrotjänster bör fungera oberoende av varandra för att tillhandahålla ett mer motståndskraftigt program. Om du inte kan leverera oberoende funktionssektorer i programmet ökar det bara komplexiteten genom att separera det.

Ett program kanske ännu inte behöver skala funktioner oberoende av varandra. Många program, när de behöver skala bortom en enda instans, kan göra det genom den relativt enkla kloningsprocessen för hela instansen. Det extra arbetet med att separera programmet i diskreta tjänster ger en minimal fördel när det är enkelt och kostnadseffektivt att skala hela instanser av programmet.

Tidigt i utvecklingen av ett program kanske du inte har en klar uppfattning om var de naturliga funktionella gränserna finns. När du utvecklar en minsta livskraftig produkt kanske den naturliga separationen ännu inte har uppstått. Vissa av dessa villkor kan vara tillfälliga. Du kan börja med att skapa ett monolitiskt program och senare separera vissa funktioner som ska utvecklas och distribueras som mikrotjänster. Andra villkor kan vara viktiga för programmets problemutrymme, vilket innebär att programmet kanske aldrig delas upp i flera mikrotjänster.

Att separera ett program i många diskreta processer medför också kostnader. Det finns mer komplexitet i att separera funktioner i olika processer. Kommunikationsprotokollen blir mer komplexa. I stället för metodanrop måste du använda asynkron kommunikation mellan tjänster. När du går över till en arkitektur för mikrotjänster måste du lägga till många av de byggstenar som implementeras i mikrotjänstversionen av eShopOnContainers-programmet: händelsebusshantering, meddelandeåterhämtning och återförsök, slutlig konsekvens med mera.

Det mycket enklare referensprogrammet eShopOnWeb stöder monolitisk containeranvändning med en container. Programmet innehåller ett webbprogram som innehåller traditionella MVC-vyer, webb-API:er och Razor Pages. Du kan också köra programmets Blazor-baserade administratörskomponent, som även kräver ett separat API-projekt.

Programmet kan startas från lösningsroten med hjälp av kommandona docker-compose build och docker-compose up . Det här kommandot konfigurerar en container för webbinstansen med hjälp av Dockerfile roten i webbprojektet och kör containern på en angiven port. Du kan ladda ned källan för det här programmet från GitHub och köra den lokalt. Även det här monolitiska programmet drar nytta av att distribueras i en containermiljö.

För det första innebär den containerbaserade distributionen att varje instans av programmet körs i samma miljö. Den här metoden omfattar utvecklarmiljön där tidig testning och utveckling sker. Utvecklingsteamet kan köra programmet i en containerbaserad miljö som matchar produktionsmiljön.

Dessutom skalas containerbaserade program ut till en lägre kostnad. Om du använder en containermiljö kan du dela resurser mer än traditionella VM-miljöer.

Slutligen tvingar containerisering av programmet en separation mellan affärslogik och lagringsservern. När programmet skalas ut förlitar sig alla flera containrar på ett enda fysiskt lagringsmedium. Det här lagringsmediet skulle vanligtvis vara en server med hög tillgänglighet som kör en SQL Server-databas.

Docker-stöd

Projektet eShopOnWeb körs på .NET. Därför kan den köras i Linux-baserade eller Windows-baserade containrar. Observera att för Docker-distribution vill du använda samma värdtyp för SQL Server. Linux-baserade containrar tillåter ett mindre fotavtryck och är att föredra.

Du kan använda Visual Studio 2017 eller senare för att lägga till Docker-stöd i ett befintligt program genom att högerklicka på ett projekt i Solution Explorer och välja Lägg till>Docker-support. Det här steget lägger till de filer som krävs och ändrar projektet så att de används. Det aktuella eShopOnWeb exemplet har redan dessa filer på plats.

Filen på lösningsnivå docker-compose.yml innehåller information om vilka avbildningar som ska skapas och vilka containrar som ska startas. Med filen kan du använda docker-compose kommandot för att starta flera program samtidigt. I det här fallet startar det bara webbprojektet. Du kan också använda den för att konfigurera beroenden, till exempel en separat databascontainer.

version: '3'

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

networks:
  default:
    external:
      name: nat

Filen docker-compose.yml refererar till Dockerfile i Web projektet. Dockerfile Används för att ange vilken bascontainer som ska användas och hur programmet ska konfigureras på den. Dockerfile" Web:

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"]

Felsöka Docker-problem

När du har kört det containerbaserade programmet fortsätter det att köras tills du stoppar det. Du kan visa vilka containrar som körs med docker ps kommandot . Du kan stoppa en container som körs med hjälp docker stop av kommandot och ange container-ID:t.

Observera att docker-containrar som körs kan vara bundna till portar som du annars kan försöka använda i utvecklingsmiljön. Om du försöker köra eller felsöka ett program med samma port som en Docker-container som körs får du ett felmeddelande om att servern inte kan binda till den porten. Om du stoppar containern igen bör du lösa problemet.

Om du vill lägga till Docker-stöd i ditt program med Hjälp av Visual Studio kontrollerar du att Docker Desktop körs när du gör det. Guiden körs inte korrekt om Docker Desktop inte körs när du startar guiden. Dessutom undersöker guiden ditt aktuella containerval för att lägga till rätt Docker-stöd. Om du vill lägga till, stöd för Windows-containrar, måste du köra guiden medan du har Docker Desktop igång med Windows-containrar konfigurerade. Om du vill lägga till, stöd för Linux-containrar, kör du guiden medan du har Docker igång med Linux-containrar konfigurerade.

Andra arkitekturformat för webbprogram

  • Web-Queue-Worker: Kärnkomponenterna i den här arkitekturen är en webbklientdel som hanterar klientbegäranden och en arbetare som utför resursintensiva uppgifter, långvariga arbetsflöden eller batchjobb. Klientdelen kommunicerar med webbarbetet via en meddelandekö.
  • N-nivå: En N-nivåarkitektur delar upp ett program i logiska lager och fysiska nivåer.
  • Mikrotjänst: En mikrotjänstarkitektur består av en samling små, autonoma tjänster. Varje tjänst är fristående och bör implementera en enda affärsfunktion i en begränsad kontext.

Referenser – vanliga webbarkitekturer