Sdílet prostřednictvím


Model moderní webové aplikace pro .NET

Azure App Service
Azure Front Door
Azure Spravovaný Redis
.NET

Tento článek ukazuje, jak implementovat model moderní webové aplikace. Model moderní webové aplikace definuje, jak byste měli modernizovat webové aplikace v cloudu a zavést architekturu zaměřenou na služby. Vzor moderní webové aplikace poskytuje preskriptivní architekturu, kód a pokyny ke konfiguraci, které odpovídají principům architektury Azure Well-Architected Framework a vychází ze vzoru Spolehlivé webové aplikace.

Proč používat vzor moderní webové aplikace?

Model moderní webové aplikace vám pomůže optimalizovat oblasti webové aplikace s vysokou poptávkou. Poskytuje podrobné pokyny pro oddělení těchto oblastí, které umožňují nezávislé škálování pro optimalizaci nákladů. Tento přístup umožňuje přidělit vyhrazené prostředky kritickým komponentám, což zvyšuje celkový výkon. Oddělení oddělených služeb může zlepšit spolehlivost tím, že brání zpomalení v jedné části aplikace, aby ovlivnily ostatní. Oddělení také umožňuje nezávisle na sobě verze jednotlivých komponent aplikace.

Implementace vzoru moderní webové aplikace

Tento článek obsahuje pokyny k architektuře, kódu a konfiguraci pro implementaci vzoru moderní webové aplikace. Následující odkazy vám posílají pokyny, které potřebujete:

  • Pokyny k architektuře Zjistěte, jak modularizovat komponenty webových aplikací a vybrat vhodná řešení typu platforma jako služba (PaaS).
  • Pokyny pro kód Implementujte čtyři vzory návrhu pro optimalizaci oddělených komponent: Strangler Fig, Queue-Based Vyrovnávání zatížení, Konkurující spotřebitelé a monitorování koncových bodů stavu.
  • Pokyny ke konfiguraci Nakonfigurujte ověřování, autorizaci, automatické škálování a kontejnerizaci pro oddělené komponenty.

Návod

Logo GitHubu Existuje referenční implementace (ukázková aplikace) vzoru moderní webové aplikace. Představuje koncový stav implementace moderní webové aplikace. Jedná se o produkční webovou aplikaci, která obsahuje všechny aktualizace kódu, architektury a konfigurace, které jsou popsány v tomto článku. Nasaďte a použijte referenční implementaci, která vás provede implementací modelu moderní webové aplikace.

Pokyny pro architekturu

Model moderní webové aplikace vychází ze vzoru Reliable Web App. K implementaci vyžaduje několik dalších komponent architektury. Potřebujete frontu zpráv, platformu kontejneru, oddělené úložiště dat služby a registr kontejnerů. Následující diagram znázorňuje základní architekturu.

diagram znázorňující základní architekturu vzoru moderní webové aplikace

Pro vyšší cíl na úrovni služby (SLO) můžete do architektury webové aplikace přidat druhou oblast. Pokud přidáte druhou oblast, musíte nakonfigurovat nástroj pro vyrovnávání zatížení tak, aby směrovat provoz do této oblasti tak, aby podporoval konfiguraci aktivní-aktivní nebo aktivní-pasivní. Pomocí hvězdicové síťové topologie můžete centralizovat a sdílet prostředky, jako je síťová brána firewall. Přístup k úložišti kontejneru prostřednictvím virtuální sítě centra. Pokud máte virtuální počítače, přidejte hostitele bastionu do virtuální sítě centra, abyste je mohli spravovat s rozšířeným zabezpečením. Následující diagram znázorňuje tuto architekturu.

Diagram znázorňující architekturu vzoru moderní webové aplikace s druhou oblastí a hvězdicovou topologií sítě

Oddělení architektury

Pokud chcete implementovat model moderní webové aplikace, musíte oddělit stávající architekturu webové aplikace. Oddělení architektury zahrnuje rozdělení monolitické aplikace do menších nezávislých služeb, které jsou zodpovědné za konkrétní funkci nebo funkce. Tento proces zahrnuje vyhodnocení aktuální webové aplikace, úpravu architektury a nakonec extrahování kódu webové aplikace na platformu kontejneru. Cílem je systematicky identifikovat a extrahovat aplikační služby, které nejvíce využívají od oddělení. Pokud chcete oddělit architekturu, postupujte podle těchto doporučení:

  • Identifikace hranic služby Použijte principy návrhu řízeného doménou k identifikaci ohraničených kontextů v monolitické aplikaci. Každý ohraničený kontext představuje logickou hranici a může být kandidátem pro samostatnou službu. Služby, které představují jedinečné obchodní funkce a mají méně závislostí, jsou vhodnými kandidáty na oddělení.

  • Vyhodnoťte výhody služby. Zaměřte se na služby, které nejvíce využívají nezávislé škálování. Oddělení těchto služeb a převod úloh zpracování od synchronních na asynchronní operace umožňuje efektivnější správu prostředků, podporuje nezávislá nasazení a snižuje riziko ovlivnění jiných částí aplikace během aktualizací nebo změn. Rezervaci objednávky můžete například oddělit od zpracování objednávek.

  • Vyhodnoťte technickou proveditelnost. Prozkoumejte aktuální architekturu a identifikujte technická omezení a závislosti, které by mohly ovlivnit proces oddělení. Naplánujte způsob správy a sdílení dat napříč službami. Oddělené služby by měly spravovat vlastní data a minimalizovat přímý přístup k databázi přes hranice služeb.

  • Nasaďte služby Azure. Vyberte a nasaďte služby Azure, které potřebujete k podpoře služby webové aplikace, kterou chcete extrahovat. Pokyny najdete v tématu Výběr správných služeb Azure.

  • Oddělte služby webových aplikací. Definujte jasná rozhraní a rozhraní API, která umožňují nově extrahovaným službám webových aplikací pracovat s dalšími částmi systému. Navrhujte strategii správy dat, která každé službě umožňuje spravovat vlastní data a zároveň zajistit konzistenci a integritu. Konkrétní strategie implementace a vzory návrhu, které se mají použít během tohoto procesu extrakce, najdete v části Pokyny kódu tohoto článku.

  • Pro oddělené služby používejte nezávislé úložiště. Každá oddělená služba by měla mít své vlastní izolované úložiště dat, aby bylo možné usnadnit nezávislou správu verzí, nasazení a škálovatelnost a zachovat integritu dat. Referenční implementace například odděluje službu vykreslování lístků od webového rozhraní API a eliminuje potřebu služby pro přístup k databázi rozhraní API. Místo toho služba předá adresu URL, kde se obrázky lístků vygenerovaly zpět do webového rozhraní API prostřednictvím zprávy služby Azure Service Bus a rozhraní API uchovává cestu ke své databázi.

  • Implementujte samostatné kanály nasazení pro každou oddělenou službu. Samostatné kanály nasazení umožňují aktualizaci jednotlivých služeb vlastním tempem. Pokud různé týmy nebo organizace ve vaší společnosti vlastní různé služby, mají samostatné kanály nasazení každému týmu kontrolu nad jejich vlastními nasazeními. K nastavení těchto kanálů použijte nástroje kontinuální integrace a průběžného doručování (CI/CD), jako je Jenkins, GitHub Actions nebo Azure Pipelines.

  • Revidovat bezpečnostní prvky Ujistěte se, že jsou vaše bezpečnostní prvky aktualizované tak, aby zahrnovaly novou architekturu, včetně pravidel brány firewall a řízení přístupu.

Výběr správných služeb Azure

Pro každou službu Azure ve vaší architektuře se podívejte na příslušného průvodce službami Azure v architektuře. Pro model moderní webové aplikace potřebujete systém zasílání zpráv, který podporuje asynchronní zasílání zpráv, aplikační platformu, která podporuje kontejnerizaci a úložiště imagí kontejneru.

  • Zvolte frontu zpráv. Fronta zpráv je důležitou součástí architektur orientovaných na služby. Oddělí odesílatele zpráv a příjemce, aby bylo možné asynchronní zasílání zpráv. Pokyny k výběru služby zasílání zpráv Azure použijte k výběru systému zasílání zpráv Azure, který podporuje vaše potřeby návrhu. Azure má tři služby zasílání zpráv: Azure Event Grid, Azure Event Hubs a Azure Service Bus. Začněte službou Service Bus jako výchozí volbou a použijte další dvě možnosti, pokud Service Bus nevyhovuje vašim potřebám.

    Služba Případ použití
    Služební autobus Zvolte Service Bus pro spolehlivé, seřazené a případně transakční doručování vysoce hodnotných zpráv v podnikových aplikacích.
    Event Grid (síť událostí) Pokud potřebujete efektivně zpracovávat velký počet diskrétních událostí, zvolte Event Grid. Event Grid je škálovatelný pro aplikace řízené událostmi, kde je potřeba směrovat mnoho malých nezávislých událostí (jako jsou změny stavu prostředků) na předplatitele v modelu publikování a odběru s nízkou latencí.
    Centra událostí Zvolte službu Event Hubs pro masivní příjem dat s vysokou propustností, jako jsou telemetrie, protokoly nebo analýzy v reálném čase. Služba Event Hubs je optimalizovaná pro scénáře streamování, ve kterých je potřeba hromadná data ingestovat a zpracovávat nepřetržitě.
  • Implementujte službu kontejneru. Pro komponenty aplikace, které chcete kontejnerizovat, potřebujete aplikační platformu, která podporuje kontejnery. Pokyny k volbě služby kontejneru Azure vám můžou pomoct při rozhodování. Azure má tři hlavní služby kontejnerů: Azure Container Apps, Azure Kubernetes Service (AKS) a Aplikace Azure Service. Začněte s Container Apps jako výchozí volbou a použijte další dvě možnosti, pokud Container Apps nevyhovuje vašim potřebám.

    Služba Případ použití
    Aplikace pro kontejnery Zvolte Container Apps, pokud potřebujete bezserverovou platformu, která automaticky škáluje a spravuje kontejnery v aplikacích řízených událostmi.
    Azure Kubernetes Service (AKS) Pokud potřebujete podrobnou kontrolu nad konfiguracemi Kubernetes a pokročilými funkcemi pro škálování, sítě a zabezpečení, zvolte AKS.
    Webové aplikace pro kontejnery Pro nejjednodušší prostředí PaaS zvolte Web App for Containers ve službě App Service.
  • Implementujte úložiště kontejneru. Pokud používáte výpočetní službu založenou na kontejneru, musíte mít úložiště pro ukládání imagí kontejneru. Můžete použít veřejný registr kontejneru, jako je Docker Hub nebo spravovaný registr, jako je Azure Container Registry. S rozhodováním vám může pomoct úvod do registrů kontejnerů v Azure .

Pokyny pro kód

Pokud chcete úspěšně oddělit a extrahovat nezávislou službu, musíte aktualizovat kód webové aplikace pomocí následujících vzorů návrhu: model strangler fig, model vyrovnávání zatížení na základě fronty, model konkurenčních spotřebitelů, model monitorování koncových bodů stavu a vzor opakování. Role těchto vzorů jsou znázorněny tady:

Diagram znázorňující role vzorů návrhu v architektuře vzoru moderní webové aplikace

  1. Model Strangler Fig: Model Strangler Fig přírůstkově migruje funkce z monolitické aplikace do oddělené služby. Tento model implementujte v hlavní webové aplikaci, aby se postupně migrovaly funkce do nezávislých služeb směrováním provozu na základě koncových bodů.

  2. Model vyrovnávání zatížení na základě fronty: Model vyrovnávání zatížení na základě fronty spravuje tok zpráv mezi producentem a příjemcem pomocí fronty jako vyrovnávací paměti. Implementujte tento vzor do základu kódu, který vytváří zprávy pro frontu. Oddělená služba pak tyto zprávy využívá asynchronně z fronty.

  3. Model Konkurenční spotřebitelé: Model Konkurující příjemci umožňuje více instancím oddělené služby nezávisle číst ze stejné fronty zpráv a soutěžit o zpracování zpráv. Tento model implementujte v oddělené službě za účelem distribuce úloh napříč několika instancemi.

  4. Model monitorování koncových bodů stavu: Model Monitorování koncových bodů stavu zveřejňuje koncové body pro monitorování stavu a stavu různých částí webové aplikace. (4a) Tento model implementujte v hlavní webové aplikaci. (4b) Implementujte ji také v oddělené službě pro sledování stavu koncových bodů.

  5. Model opakování: Vzor opakování zpracovává přechodné selhání opakováním operací, které můžou občas selhat. (5a) Tento model implementujte u všech odchozích volání do jiných služeb Azure v hlavní webové aplikaci, jako jsou volání fronty zpráv a privátní koncové body. (5b) Tento model implementujte také v oddělené službě, která zpracovává přechodné chyby při volání privátních koncových bodů.

Každý vzor návrhu poskytuje výhody, které odpovídají jednomu nebo více pilířům architektury Well-Architected. Podrobnosti najdete v následující tabulce.

Návrhový vzor Umístění implementace Spolehlivost (RE) Zabezpečení (SE) Optimalizace nákladů (CO) Efektivita provozu (OE) Efektivita výkonu (PE) Podpora dobře navržených principů architektury
Fíkový vzor škrtiče Hlavní webová aplikace RE:08 řekl:
CO:07
CO:08
OE:06
OE:11
Model vyrovnávání zatížení na základě fronty Hlavní webová aplikace (producent zpráv) RE:07 řekl:
RE:07 řekl:
CO:12
PE:05
Model konkurenčních spotřebitelů Oddělená služba RE:05 řekl:
RE:07 řekl:
CO:05
CO:07
PE:05
PE:07
Model monitorování koncových bodů stavu Hlavní webová aplikace a oddělená služba RE:07 řekl:
RE:10
OE:07
PE:05
Vzor Opakování Hlavní webová aplikace a oddělená služba RE:07 řekl:

Implementace vzoru Strangler Fig

Pomocí modelu Strangler Fig můžete postupně migrovat funkce z monolitického základu kódu do nových nezávislých služeb. Extrahujte nové služby z existujícího monolitického základu kódu a pomalu modernizujte důležité části webové aplikace. Při implementaci modelu Strangler Fig postupujte podle těchto doporučení:

  • Nastavte vrstvu směrování. V monolitickém základu kódu webové aplikace implementujte vrstvu směrování, která směruje provoz na základě koncových bodů. Použijte vlastní logiku směrování podle potřeby ke zpracování konkrétních obchodních pravidel pro směrování provozu. Pokud máte například v monolitické aplikaci koncový bod /users a tuto funkci přesunete do oddělené služby, směrovací vrstva směruje všechny požadavky na /users do nové služby.

  • Správa zavedení funkcí Pomocí knihoven pro správu funkcí .NET implementujte příznaky funkcí a postupné zavádění pro postupné zavádění oddělených služeb. Stávající monolitické směrování aplikací by mělo řídit, kolik žádostí oddělené služby obdrží. Začněte s malým procentem požadavků a zvyšte využití v průběhu času, protože získáte jistotu o stabilitě a výkonu nové služby. Například referenční implementace extrahuje funkci vykreslování lístků do samostatné služby, která se dá postupně zavést pro zpracování větší části požadavků na vykreslování lístků. Vzhledem k tomu, že nová služba prokáže svou spolehlivost a výkon, může nakonec převzít celou funkci vykreslování lístků z monolitu a dokončit přechod.

  • Použijte fasádní službu (v případě potřeby). Služba fasády je užitečná, když jeden požadavek potřebuje pracovat s více službami nebo když chcete skrýt složitost základního systému před klientem. Pokud však oddělená služba nemá žádná veřejná rozhraní API, nemusí být nutná služba fasády. V monolitickém základu kódu webové aplikace implementujte façade službu pro směrování požadavků na příslušný back-end (monolitické nebo mikroslužby). V nové oddělené službě se ujistěte, že nová služba může zpracovávat požadavky nezávisle při přístupu přes fasádu.

Implementace modelu vyrovnávání zatížení na základě fronty

Implementujte model vyrovnávání zatížení na základě fronty v části producenta oddělené služby tak, aby asynchronně zpracovával úlohy, které nepotřebují okamžité odpovědi. Tento model zlepšuje celkovou odezvu systému a škálovatelnost pomocí fronty ke správě distribuce úloh. Umožňuje oddělení služby zpracovávat požadavky konzistentní rychlostí. Pokud chcete tento model efektivně implementovat, postupujte podle těchto doporučení:

  • Použití odblokování front zpráv Ujistěte se, že proces, který odesílá zprávy do fronty, neblokuje jiné procesy při čekání na oddělení služby pro zpracování zpráv ve frontě. Pokud proces vyžaduje výsledek operace oddělené služby, máte alternativní způsob, jak zvládnout situaci při čekání na dokončení operace ve frontě. Například referenční implementace používá Service Bus a await klíčové slovo s messageSender.PublishAsync() k asynchronnímu publikování zpráv do fronty bez blokování vlákna, které spouští tento kód:

    // Asynchronously publish a message without blocking the calling thread.
    await messageSender.PublishAsync(new TicketRenderRequestMessage(Guid.NewGuid(), ticket, null, DateTime.Now), CancellationToken.None);
    

    Tento přístup zajišťuje, aby hlavní aplikace zůstala responzivní a dokázala zpracovávat další úlohy současně, zatímco oddělená služba zpracovává požadavky zařazené do fronty s možností správy.

  • Implementujte opakování a odebrání zprávy. Implementujte mechanismus pro opakování zpracování zpráv ve frontě, které nelze úspěšně zpracovat. Pokud chyby potrvají, měly by se tyto zprávy z fronty odebrat. Service Bus má například integrované funkce fronty opakování a nedoručených zpráv.

  • Nakonfigurujte zpracování idempotentních zpráv. Logika, která zpracovává zprávy z fronty, musí být idempotentní pro zpracování případů, kdy může být zpráva zpracována více než jednou. Například referenční implementace používá ServiceBusClient.CreateProcessor s AutoCompleteMessages = true a ReceiveMode = ServiceBusReceiveMode.PeekLock k zajištění, aby zprávy byly zpracovány pouze jednou a je možné je znovu zpracovat při selhání. Tuto logiku ilustruje následující kód.

    // Create a processor for idempotent message processing.
    var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions
    {
        // Allow the messages to be auto-completed
        // if processing finishes without failure.
        AutoCompleteMessages = true,
    
        // PeekLock mode provides reliability in that unsettled messages
        // will be redelivered on failure.
        ReceiveMode = ServiceBusReceiveMode.PeekLock,
    
        // Containerized processors can scale at the container level
        // and need not scale via the processor options.
        MaxConcurrentCalls = 1,
        PrefetchCount = 0
    });
    
  • Umožňuje spravovat změny prostředí. Asynchronní zpracování může vést k tomu, že se úlohy okamžitě nedokončují. Uživatelé by měli vědět, kdy se jejich úkol stále zpracovává, aby nastavili správná očekávání a vyhnuli se nejasnostem. Pomocívizuálních Poskytněte uživatelům možnost dostávat oznámení, když je úkol hotový, například e-mail nebo nabízené oznámení.

Implementace modelu Konkurenční spotřebitelé

Implementujte model Konkurenční spotřebitelé v oddělených službách za účelem správy příchozích úkolů z fronty zpráv. Tento model zahrnuje distribuci úloh napříč několika instancemi oddělených služeb. Tyto služby zpracovávají zprávy z fronty, vylepšují vyrovnávání zatížení a zvyšují kapacitu systému pro zpracování souběžných požadavků. Model Konkurenční spotřebitelé je účinný v následujících případech:

  • Posloupnost zpracování zpráv není zásadní.
  • Fronta zůstává nedotčena poškozenými zprávami.
  • Operace zpracování je idempotentní, což znamená, že ji lze použít vícekrát, aniž by se změnil výsledek nad rámec počáteční aplikace.

Pokud chcete implementovat model Konkurenční spotřebitelé, postupujte podle těchto doporučení:

  • Zpracování souběžných zpráv Když systém přijímá zprávy z fronty, ujistěte se, že je systém navržený tak, aby zpracovával více zpráv současně. Nastavte maximální počet souběžných volání na 1, aby jednotliví příjemci zpracovávali každou zprávu.

  • Zakažte předběžné načítání. Zakažte předběžné načítání zpráv, aby příjemci načítali zprávy jenom tehdy, když jsou připravení.

  • Používejte spolehlivé režimy zpracování zpráv. Použijte spolehlivý režim zpracování, například PeekLock (nebo jeho ekvivalent), který automaticky opakuje zprávy, které selžou zpracování. Tento režim poskytuje větší spolehlivost než metody první odstranění. Pokud se jednomu pracovnímu procesu nepodaří zpracovat zprávu, musí být jiný schopen ji zpracovat bez chyb, a to i v případě, že je zpráva zpracována vícekrát.

  • Implementujte zpracování chyb. Směrování poškozených nebo nezpracovaných zpráv do samostatné fronty nedoručených zpráv Tento návrh zabraňuje opakovanému zpracování. Můžete například zachytit výjimky během zpracování zpráv a přesunout problematickou zprávu do samostatné fronty.

  • Zpracování zpráv mimo pořadí Navrhnou uživatele pro zpracování zpráv, které přicházejí z posloupnosti. Pokud máte více paralelních příjemců, můžou zpracovávat zprávy mimo pořadí.

  • Škálování na základě délky fronty Služby využívající zprávy z fronty by měly zvážit automatické škálování na základě délky fronty nebo použití dalších kritérií škálování pro lepší zpracování špiček příchozích zpráv.

  • Použijte frontu pro odpovědi na zprávy. Pokud systém vyžaduje oznámení pro následné zpracování zpráv, nastavte vyhrazenou frontu odpovědí nebo odpovědí. Toto nastavení rozdělí provozní zasílání zpráv z procesů oznámení.

  • Používejte bezstavové služby. Zvažte použití bezstavových služeb ke zpracování požadavků z fronty. Tyto služby umožňují snadné škálování a efektivní využití prostředků.

  • Nakonfigurujte protokolování. Integrujte protokolování a zpracování konkrétních výjimek v rámci pracovního postupu zpracování zpráv. Zaměřte se na zachycení chyb serializace a nasměrování těchto problematických zpráv do mechanismu nedoručených zpráv. Tyto protokoly poskytují cenné přehledy pro řešení potíží.

Například referenční implementace používá model Konkurující příjemci ve bezstavové službě spuštěné v Container Apps ke zpracování žádostí o vykreslování lístků z fronty služby Service Bus. Konfiguruje procesor fronty pomocí:

  • AutoCompleteMessages. Automaticky dokončí zprávy, pokud se zpracovávají bez selhání.
  • ReceiveMode. Pokud se neurovnají, použije režim PeekLock a znovu odešle zprávy.
  • MaxConcurrentCalls. Nastavte na 1 pro zpracování jedné zprávy najednou.
  • PrefetchCount. Nastavte na hodnotu 0, abyste se vyhnuli předběžnému načítání zpráv.

Procesor protokoluje podrobnosti zpracování zpráv, které můžou pomoct s řešením potíží a monitorováním. Zaznamenává chyby deserializace a směruje neplatné zprávy do fronty nedoručených zpráv, aby se zabránilo opakovanému zpracování chybných zpráv. Služba se škáluje na úrovni kontejneru, což umožňuje efektivní zpracování špiček zpráv na základě délky fronty.

// Create a processor for the given queue that will process
// incoming messages.
var processor = serviceBusClient.CreateProcessor(path, new ServiceBusProcessorOptions
{
    // Allow the messages to be auto-completed
    // if processing finishes without failure.
    AutoCompleteMessages = true,
    // PeekLock mode provides reliability in that unsettled messages
    // are redelivered on failure.
    ReceiveMode = ServiceBusReceiveMode.PeekLock,
    // Containerized processors can scale at the container level
    // and need not scale via the processor options.
    MaxConcurrentCalls = 1,
    PrefetchCount = 0
});

// Called for each message received by the processor.
processor.ProcessMessageAsync += async args =>
{
    logger.LogInformation("Processing message {MessageId} from {ServiceBusNamespace}/{Path}", args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
    // Unhandled exceptions in the handler will be caught by
    // the processor and result in abandoning and dead-lettering the message.
    try
    {
        var message = args.Message.Body.ToObjectFromJson<T>();
        await messageHandler(message, args.CancellationToken);
        logger.LogInformation("Successfully processed message {MessageId} from {ServiceBusNamespace}/{Path}",args.Message.MessageId, args.FullyQualifiedNamespace, args.EntityPath);
    }
    catch (JsonException)
    {
        logger.LogError("Invalid message body; could not be deserialized to {Type}", typeof(T));
        await args.DeadLetterMessageAsync(args.Message, $"Invalid message body; could not be deserialized to {typeof(T)}",cancellationToken: args.CancellationToken);
    }
};

Implementace modelu monitorování koncových bodů stavu

Implementujte model monitorování koncových bodů stavu v hlavním kódu aplikace a oddělte kód služby pro sledování stavu koncových bodů aplikace. Orchestrátory, jako jsou AKS nebo Container Apps, můžou tyto koncové body dotazovat, aby ověřili stav služby a restartoval instance, které nejsou v pořádku. ASP.NET aplikace Core můžou přidat vyhrazený middleware pro kontrolu stavu, který efektivně obsluhuje data o stavu koncového bodu a klíčové závislosti. Pokud chcete implementovat model monitorování koncových bodů stavu, postupujte podle těchto doporučení:

  • Implementujte kontroly stavu. K zajištění koncových bodů kontroly stavu použijte middleware ASP.NET Core Health Checks.

  • Ověřte závislosti. Ujistěte se, že kontroly stavu ověřují dostupnost klíčových závislostí, jako je databáze, úložiště a systém zasílání zpráv. Balíček mimo Microsoft AspNetCore.Diagnostics.HealthChecks může implementovat kontroly závislostí kontroly stavu pro řadu běžných závislostí aplikací.

    Referenční implementace například používá ASP.NET middleware kontroly stavu Core k zveřejnění koncových bodů kontroly stavu. Používá metodu AddHealthChecks() na objektu builder.Services . Kód ověří dostupnost klíčových závislostí, Azure Blob Storage a fronty Service Bus pomocí AddAzureBlobStorage() a AddAzureServiceBusQueue() metod, které jsou součástí AspNetCore.Diagnostics.HealthChecks balíčku. Container Apps umožňuje nakonfigurovat sondy stavu, které jsou monitorované, aby se měřily, jestli jsou aplikace v pořádku nebo potřebují recyklaci.

    // Add health checks, including health checks for Azure services
    // that are used by this service.
    // The Blob Storage and Service Bus health checks are provided by
    // AspNetCore.Diagnostics.HealthChecks
    // (a popular open source project) rather than by Microsoft. 
    // https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks
    builder.Services.AddHealthChecks()
    .AddAzureBlobStorage(options =>
    {
        // AddAzureBlobStorage will use the BlobServiceClient registered in DI.
        // We just need to specify the container name.
        options.ContainerName = builder.Configuration.GetRequiredConfigurationValue("App:StorageAccount:Container");
    })
    .AddAzureServiceBusQueue(
        builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:Host"),
        builder.Configuration.GetRequiredConfigurationValue("App:ServiceBus:RenderRequestQueueName"),
        azureCredentials);
    
    // Further app configuration omitted for brevity.
    app.MapHealthChecks("/health");
    
  • Konfigurace prostředků Azure Nakonfigurujte prostředky Azure tak, aby používaly adresy URL kontroly stavu aplikace k potvrzení aktivity a připravenosti. Například referenční implementace používá Bicep ke konfiguraci adres URL kontroly stavu pro potvrzení aktivity a připravenosti prostředku Azure. Sonda aktivity se do koncového /health bodu dostane každých 10 sekund po počátečním zpoždění 2 sekundy.

    probes: [
      {
        type: 'liveness'
        httpGet: {
          path: '/health'
          port: 8080
        }
        initialDelaySeconds: 2
        periodSeconds: 10
      }
    ]
    

Implementace vzoru opakování

Model opakování umožňuje aplikacím zotavit se z přechodných chyb. Model Opakování je centrální pro model Reliable Web App, takže vaše webová aplikace by už měla používat model Opakování. Použijte vzor Opakování na požadavky na systémy zasílání zpráv a požadavky vydané oddělenými službami, které extrahujete z webové aplikace. Pokud chcete implementovat vzor opakování, postupujte podle těchto doporučení:

  • Nakonfigurujte možnosti opakování. Při integraci s frontou zpráv nezapomeňte nakonfigurovat klienta, který odpovídá za interakci s frontou s odpovídajícím nastavením opakování. Zadejte parametry, jako je maximální počet opakování, zpoždění mezi opakovanými pokusy a maximální zpoždění.

  • Používejte exponenciální zpochybnění. Implementujte exponenciální strategii zpoždování pro pokusy o opakování. Tato strategie zahrnuje zvýšení doby mezi jednotlivými opakováními exponenciálně, což pomáhá snížit zatížení systému v obdobích vysokého počtu selhání.

  • Použijte funkci opakování sady SDK. Pro služby se specializovanými sadami SDK, jako je Service Bus nebo Blob Storage, použijte integrované mechanismy opakování. Integrované mechanismy opakování jsou optimalizované pro obvyklé případy použití služby a můžou zpracovávat opakování efektivněji s méně požadovanou konfigurací. Například referenční implementace používá předdefinované funkce opakování sady Service Bus SDK (ServiceBusClient a ServiceBusRetryOptions). Objekt ServiceBusRetryOptions načte nastavení MessageBusOptions pro konfiguraci nastavení opakování, jako je MaxRetries, Delay, MaxDelaya TryTimeout.

    // ServiceBusClient is thread-safe and can be reused for the lifetime
    // of the application.
    services.AddSingleton(sp =>
    {
        var options = sp.GetRequiredService<IOptions<MessageBusOptions>>().Value;
        var clientOptions = new ServiceBusClientOptions
        {
            RetryOptions = new ServiceBusRetryOptions
            {
                Mode = ServiceBusRetryMode.Exponential,
                MaxRetries = options.MaxRetries,
                Delay = TimeSpan.FromSeconds(options.BaseDelaySecondsBetweenRetries),
                MaxDelay = TimeSpan.FromSeconds(options.MaxDelaySeconds),
                TryTimeout = TimeSpan.FromSeconds(options.TryTimeoutSeconds)
            }
        };
        return new ServiceBusClient(options.Host, azureCredential ?? new DefaultAzureCredential(), clientOptions);
    });
    
  • Přijměte standardní knihovny odolnosti pro klienty HTTP. Pro komunikaci HTTP integrujte standardní knihovnu odolnosti, jako je Polly nebo Microsoft.Extensions.Http.Resilience. Tyto knihovny nabízejí komplexní mechanismy opakování, které jsou zásadní pro správu komunikace s externími webovými službami.

  • Zpracování uzamčení zpráv U systémů založených na zprávách implementujte strategie zpracování zpráv, které podporují opakování bez ztráty dat, jako je použití režimů peek-lock, pokud jsou k dispozici. Po opakovaných selháních se ujistěte, že se neúspěšné zprávy efektivně opakují a přesunou se do fronty nedoručených zpráv.

Implementace distribuovaného trasování

S tím, jak se aplikace stávají více orientovanými na služby a jejich komponenty jsou oddělené, je monitorování toku provádění mezi službami zásadní. Model moderní webové aplikace používá Application Insights a Azure Monitor k získání přehledu o stavu a výkonu aplikací prostřednictvím rozhraní API OpenTelemetry, která podporují distribuované trasování.

Distribuované trasování sleduje požadavek uživatele při procházení více služeb. Při přijetí požadavku se označí identifikátorem trasování, který se předá jiným komponentám prostřednictvím hlaviček HTTP a vlastnosti služby Service Bus během vyvolání závislostí. Trasování a protokoly pak zahrnují identifikátor trasování i identifikátor aktivity (nebo identifikátor rozsahu), který odpovídá konkrétní komponentě a její nadřazené aktivitě. Monitorovací nástroje, jako je Application Insights, používají tyto informace k zobrazení stromu aktivit a protokolů napříč různými službami, což je zásadní pro monitorování distribuovaných aplikací.

  • Nainstalujte knihovny OpenTelemetry. Pomocí knihoven instrumentace můžete povolit trasování a metriky z běžných komponent. Přidejte vlastní instrumentaci s System.Diagnostics.ActivitySource a System.Diagnostics.Activity v případě potřeby. Pomocí knihoven exportéru můžete naslouchat diagnostice OpenTelemetry a zaznamenávat je v trvalých úložištích. Použijte existující vývozce nebo vytvořte vlastní pomocí System.Diagnostics.ActivityListener.

  • Nastavte OpenTelemetry. Použijte distribuci OpenTelemetry (Azure.Monitor.OpenTelemetry.AspNetCore) služby Azure Monitor. Ujistěte se, že exportuje diagnostiku do Application Insights a zahrnuje integrovanou instrumentaci pro běžné metriky, trasování, protokoly a výjimky z modulu runtime .NET a ASP.NET Core. Zahrňte další balíčky instrumentace OpenTelemetry pro klienty SQL, Redis a Azure SDK.

  • Monitorování a analýza Po konfiguraci trasování se ujistěte, že se protokoly, trasování, metriky a výjimky zaznamenávají a odesílají do Application Insights. Ověřte, že jsou zahrnuté identifikátory trasování, aktivity a nadřazené aktivity. Tyto identifikátory umožňují Application Insights poskytovat kompletní přehled trasování napříč hranicemi HTTP a Service Bus. Pomocí tohoto nastavení můžete monitorovat a analyzovat aktivity vaší aplikace napříč službami.

Ukázka moderní webové aplikace používá distribuci OpenTelemetry (Azure.Monitor.OpenTelemetry.AspNetCore) služby Azure Monitor. Další balíčky instrumentace se používají pro klienty SQL, Redis a Azure SDK. OpenTelemetry se konfiguruje ve službě moderní webové aplikace pro vykreslování lístků takto:

builder.Logging.AddOpenTelemetry(o => 
{ 
    o.IncludeFormattedMessage = true; 
    o.IncludeScopes = true; 
}); 

builder.Services.AddOpenTelemetry() 
    .UseAzureMonitor(o => o.ConnectionString = appInsightsConnectionString) 
    .WithMetrics(metrics => 
    { 
        metrics.AddAspNetCoreInstrumentation() 
                .AddHttpClientInstrumentation() 
                .AddRuntimeInstrumentation(); 
    }) 
    .WithTracing(tracing => 
    { 
        tracing.AddAspNetCoreInstrumentation() 
                .AddHttpClientInstrumentation() 
                .AddSource("Azure.*"); 
    }); 

Metoda builder.Logging.AddOpenTelemetry směruje veškeré protokolování přes OpenTelemetry, aby se zajistilo konzistentní trasování a protokolování napříč aplikací. Vzhledem k tomu, že jsou služby OpenTelemetry zaregistrované builder.Services.AddOpenTelemetry, je aplikace nastavena tak, aby shromažďovala a exportovala diagnostiku, která se pak odesílají do Application Insights prostřednictvím UseAzureMonitor. Kromě toho je instrumentace klientů pro komponenty, jako je Service Bus a klienti HTTP, nakonfigurována WithMetrics a WithTracing, což umožňuje automatické metriky a shromažďování trasování, aniž by bylo nutné změnit stávající využití klienta. Vyžaduje se pouze aktualizace konfigurace.

Pokyny ke konfiguraci

Následující části obsahují pokyny k implementaci aktualizací konfigurace. Každý oddíl je v souladu s jedním nebo více pilíři dobře navržená architektura.

Konfigurace Spolehlivost (RE) Zabezpečení (SE) Optimalizace nákladů (CO) Efektivita provozu (OE) Efektivita výkonu (PE) Podpora dobře navržených principů architektury
Konfigurace ověřování a autorizace SE:05 řekl:
OE:10
Implementace nezávislého automatického škálování RE:06 řekl:
CO:12
PE:05
Nasazení služby Containerize CO:13
PE:09
PE:03

Konfigurace ověřování a autorizace

Pokud chcete nakonfigurovat ověřování a autorizaci u všech nových služeb Azure (identit úloh), které přidáte do webové aplikace, postupujte podle těchto doporučení:

  • Používejte spravované identity pro každou novou službu. Každá nezávislá služba by měla mít vlastní identitu a používat spravované identity pro ověřování mezi službami. Spravované identity eliminují potřebu správy přihlašovacích údajů v kódu a snižují riziko úniku přihlašovacích údajů. Pomáhají vám vyhnout se vkládání citlivých informací, jako jsou připojovací řetězec do kódu nebo konfiguračních souborů.

  • Udělte každé nové službě nejnižší oprávnění. Každému novému identitě služby přiřaďte pouze potřebná oprávnění. Pokud například identita potřebuje odeslat jenom do registru kontejneru, neudělujte jí oprávnění k přijetí změn. Tato oprávnění pravidelně zkontrolujte a podle potřeby je upravte. Pro různé role, jako je nasazení a aplikace, použijte různé identity. Tím se omezí potenciální poškození, pokud dojde k ohrožení jedné identity.

  • Přijmout infrastrukturu jako kód (IaC). K definování a správě cloudových prostředků použijte bicep nebo podobné nástroje IaC. IaC zajišťuje konzistentní použití konfigurací zabezpečení ve vašich nasazeních a umožňuje řídit verze nastavení infrastruktury.

Pokud chcete nakonfigurovat ověřování a autorizaci pro uživatele (identity uživatelů), postupujte podle těchto doporučení:

  • Udělte uživatelům nejnižší oprávnění. Stejně jako u služeb zajistěte, aby uživatelům byla udělena pouze oprávnění, která potřebují k provádění svých úkolů. Pravidelně kontrolujte a upravujte tato oprávnění.

  • Proveďte pravidelné audity zabezpečení. Pravidelně kontrolujte a auditujte nastavení zabezpečení. Vyhledejte všechny chybné konfigurace nebo nepotřebná oprávnění a okamžitě je opravte.

Referenční implementace používá IaC k přiřazování spravovaných identit do přidaných služeb a konkrétních rolí ke každé identitě. Definuje role a přístup k oprávněním pro nasazení (containerRegistryPushRoleId), vlastníka aplikace (containerRegistryPushRoleId) a aplikaci Container Apps (containerRegistryPullRoleId). Následující příklad znázorňuje kód.

roleAssignments: \[
    {
    principalId: deploymentSettings.principalId
    principalType: deploymentSettings.principalType
    roleDefinitionIdOrName: containerRegistryPushRoleId
    }
    {
    principalId: ownerManagedIdentity.outputs.principal_id
    principalType: 'ServicePrincipal'
    roleDefinitionIdOrName: containerRegistryPushRoleId
    }
    {
    principalId: appManagedIdentity.outputs.principal_id
    principalType: 'ServicePrincipal'
    roleDefinitionIdOrName: containerRegistryPullRoleId
    }
\]

Referenční implementace přiřazuje spravovanou identitu jako novou identitu Container Apps při nasazení:

module renderingServiceContainerApp 'br/public:avm/res/app/container-app:0.1.0' = {
  name: 'application-rendering-service-container-app'
  scope: resourceGroup()
  params: {
    // Other parameters omitted for brevity.
    managedIdentities: {
      userAssignedResourceIds: [
        managedIdentity.id
      ]
    }
  }
}

Konfigurace nezávislého automatického škálování

Model moderní webové aplikace začíná roztřídět monolitickou architekturu a zavádí oddělení služeb. Když oddělíte architekturu webové aplikace, můžete nezávisle škálovat oddělené služby. Škálování služeb Azure tak, aby podporovaly nezávislou službu webové aplikace, nikoli celou webovou aplikaci, optimalizuje náklady na škálování při splnění požadavků. Pokud chcete kontejnery automaticky škálovat, postupujte podle těchto doporučení:

  • Používejte bezstavové služby. Ujistěte se, že vaše služby nejsou bezstavové. Pokud vaše aplikace .NET obsahuje stav relace v procesu, externalizujte ji do distribuované mezipaměti, jako je Redis nebo databáze, jako je SQL Server.

  • Nakonfigurujte pravidla automatického škálování. Použijte konfigurace automatického škálování, které poskytují nákladově nejefektivnější kontrolu nad vašimi službami. U kontejnerizovaných služeb poskytuje škálování založené na událostech, jako je Kubernetes Event-Driven Autoscaler (KEDA), často podrobné řízení, které umožňuje škálování na základě metrik událostí. Container Apps a AKS podporují KEDA. Pro služby, které nepodporují KEDA, jako je App Service, použijte funkce automatického škálování, které platforma poskytuje. Mezi tyto funkce často patří škálování založené na pravidlech založených na metrikách nebo provozu HTTP.

  • Nakonfigurujte minimální repliky. Pokud chcete zabránit studenému startu, nakonfigurujte nastavení automatického škálování tak, aby zachovalo minimálně jednu repliku. Při inicializaci služby ze zastaveného stavu dojde ke studenému startu , což často vytváří zpožděnou odpověď. Pokud je minimalizace nákladů prioritou a můžete tolerovat zpoždění studeného spuštění, nastavte při konfiguraci automatického škálování minimální počet replik na 0.

  • Nakonfigurujte období cooldownu. K zavedení zpoždění mezi událostmi škálování použijte odpovídající období cooldownu. Cílem je zabránit nadměrnému škálování aktivit, které se aktivují dočasnými špičkami zatížení.

  • Nakonfigurujte škálování na základě fronty. Pokud vaše aplikace používá frontu zpráv, jako je Service Bus, nakonfigurujte nastavení automatického škálování tak, aby se škálovat na základě délky fronty se zprávami požadavku. Cílem škálování je udržovat jednu repliku služby pro všechny N zprávy ve frontě (zaokrouhleno nahoru).

Referenční implementace například pomocí škálovače KEDA služby Service Bus škáluje aplikaci kontejneru na základě délky fronty. Škáluje service-bus-queue-length-rule službu na základě délky zadané fronty služby Service Bus. Parametr messageCount je nastavený na 10, takže škálovač má jednu repliku služby pro každých 10 zpráv ve frontě. Parametry scaleMaxReplicas nastaví scaleMinReplicas maximální a minimální počet replik pro službu. Tajný queue-connection-string klíč, který obsahuje připojovací řetězec pro frontu služby Service Bus, se načte ze služby Azure Key Vault. Tento tajný klíč slouží k ověření škálovače ve službě Service Bus.

scaleRules: [
  {
    name: 'service-bus-queue-length-rule'
    custom: {
      type: 'azure-servicebus'
      metadata: {
        messageCount: '10'
        namespace: renderRequestServiceBusNamespace
        queueName: renderRequestServiceBusQueueName
      }
      auth: [
        {
          secretRef: 'render-request-queue-connection-string'
          triggerParameter: 'connection'
        }
      ]
    }
  }
]

scaleMaxReplicas: 5
scaleMinReplicas: 0

Nasazení služby Containerize

V kontejnerizovaném nasazení se všechny závislosti vyžadované aplikací zapouzdřují do odlehčené image, která se dá spolehlivě nasadit do široké škály hostitelů. Pokud chcete nasazení kontejnerizovat, postupujte podle těchto doporučení:

  • Identifikujte hranice domény. Začněte tím, že v monolitické aplikaci identifikujete hranice domény. To vám pomůže určit, které části aplikace je možné extrahovat do samostatných služeb.

  • Vytváření imagí Dockeru Při vytváření imagí Dockeru pro služby .NET použijte chycené základní image. Tyto image obsahují pouze minimální sadu balíčků potřebných ke spuštění .NET, což minimalizuje velikost balíčku i prostor pro útok.

  • Použijte vícefázové soubory Dockerfile. Implementujte vícefázové soubory Dockerfile pro oddělení prostředků času sestavení od image kontejneru modulu runtime. Použití tohoto typu souboru pomáhá udržovat produkční image malé a zabezpečené.

  • Spusťte ho jako uživatele, který není v kořenovém adresáři. Kontejnery .NET spusťte jako uživatele, který není v kořenovém adresáři (prostřednictvím uživatelského jména nebo UID $APP_UID), aby byl v souladu s principem nejnižších oprávnění. Tím omezíte potenciální účinky ohroženého kontejneru.

  • Poslouchejte na portu 8080. Když spouštíte kontejnery jako uživatel, který není v kořenovém adresáři, nakonfigurujte aplikaci tak, aby naslouchala na portu 8080. Toto je běžná konvence pro uživatele, kteří nejsou kořeny.

  • Zapouzdření závislostí Ujistěte se, že jsou všechny závislosti pro aplikaci zapouzdřené v imagi kontejneru Dockeru. Zapouzdření umožňuje spolehlivě nasadit aplikaci do široké škály hostitelů.

  • Zvolte správné základní image. Základní image, kterou zvolíte, závisí na vašem prostředí nasazení. Pokud například nasazujete do Container Apps, musíte použít image Dockeru pro Linux.

Například referenční implementace používá vícefázový proces sestavení. Počáteční fáze kompilují a sestavují aplikaci pomocí úplné image sady SDK (mcr.microsoft.com/dotnet/sdk:8.0-jammy). Konečná image modulu runtime se vytvoří ze chiseled základní image, která vylučuje sadu SDK a artefakty sestavení. Služba běží jako uživatel bez kořene aUSER $APP_UID zveřejňuje port 8080. Závislosti potřebné pro fungování aplikace jsou zahrnuty do image Dockeru, jak ukazují příkazy ke kopírování souborů projektu a obnovení balíčků. Použití imagí založených na Linuxu (mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled) zajišťuje kompatibilitu s Container Apps, která vyžaduje kontejnery Linuxu pro nasazení.

# Build in a separate stage to avoid copying the SDK into the final image.
FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src

# Restore packages.
COPY ["Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj", "Relecloud.TicketRenderer/"]
COPY ["Relecloud.Messaging/Relecloud.Messaging.csproj", "Relecloud.Messaging/"]
COPY ["Relecloud.Models/Relecloud.Models.csproj", "Relecloud.Models/"]
RUN dotnet restore "./Relecloud.TicketRenderer/Relecloud.TicketRenderer.csproj"

# Build and publish.
COPY . .
WORKDIR "/src/Relecloud.TicketRenderer"
RUN dotnet publish "./Relecloud.TicketRenderer.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

# Chiseled images contain only the minimal set of packages needed for .NET 8.0.
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS final
WORKDIR /app
EXPOSE 8080

# Copy the published app from the build stage.
COPY --from=build /app/publish .

# Run as nonroot user.
USER $APP_UID
ENTRYPOINT ["dotnet", "./Relecloud.TicketRenderer.dll"]

Nasazení referenční implementace

Nasaďte referenční implementaci moderního vzoru webové aplikace pro .NET. V úložišti jsou pokyny pro vývoj i produkční nasazení. Po nasazení implementace můžete simulovat a sledovat vzory návrhu.

Následující diagram znázorňuje architekturu referenční implementace:

Diagram znázorňující architekturu referenční implementace

Stáhněte si soubor aplikace Visio s touto architekturou.