Sdílet prostřednictvím


Implementace systému jističe

Návod

Tento obsah je výňatek z eBooku, architektury mikroslužeb .NET pro kontejnerizované aplikace .NET, které jsou k dispozici na .NET Docs nebo jako zdarma ke stažení PDF, které lze číst offline.

eBook o architektuře mikroslužeb .NET pro kontejnerizované aplikace .NET, miniatura na obálce.

Jak jsme uvedli dříve, měli byste zpracovávat chyby, které můžou trvat různou dobu, než se obnoví, jak se může stát při pokusu o připojení ke vzdálené službě nebo prostředku. Zpracování tohoto typu chyby může zlepšit stabilitu a odolnost aplikace.

V distribuovaném prostředí můžou volání vzdálených prostředků a služeb selhat kvůli přechodným chybám, jako jsou pomalé síťová připojení a vypršení časového limitu, nebo pokud prostředky reagují pomalu nebo jsou dočasně nedostupné. Tyto chyby se obvykle opravují po krátké době a robustní cloudová aplikace by se měla připravit na jejich zpracování pomocí strategie, jako je například model opakování.

Mohou však také nastat situace, kdy chyby jsou způsobeny neočekávajícími událostmi, které mohou trvat mnohem déle, než se opraví. Tyto chyby můžou být různě závažné, od částečného výpadku připojení až po úplné selhání služby. V těchto situacích může být pro aplikaci zbytečné neustále opakovat operaci, která pravděpodobně nebude úspěšná.

Místo toho by měla být aplikace zakódovaná tak, aby přijímala, že operace selhala, a odpovídajícím způsobem zpracovat selhání.

Bezstarostným použitím opakování HTTP může dojít k útoku typu DoS ve vašem vlastním softwaru. Vzhledem k tomu, že mikroslužba selže nebo funguje pomalu, může několik klientů opakovaně opakovat neúspěšné požadavky. To vytváří nebezpečné riziko exponenciálního zvýšení provozu cíleného na neúspěšnou službu.

Proto potřebujete nějaký druh ochranné bariéry, aby se nadměrné požadavky zastavily, když to nestojí za to pokračovat v pokusu. Tato bariéra obrany je přesně jistič.

Model Jističů má jiný účel než model opakování. Model opakování umožňuje aplikaci opakovat operaci v očekávání, že operace bude nakonec úspěšná. Model Jistič brání aplikaci v provádění operace, která pravděpodobně selže. Aplikace může tyto dva vzory kombinovat. Logika opakování by však měla být citlivá na všechny výjimky vrácené jističem a měla by opustit pokusy o opakování, pokud jistič indikuje, že chyba není přechodná.

Implementace modelu Jistič pomocí IHttpClientFactory a Polly

Stejně jako u implementace opakování, doporučený přístup pro jističe je využít osvědčené knihovny .NET, jako je Polly, a její nativní integraci s IHttpClientFactory.

Přidání politiky jističe do IHttpClientFactory odchozího kanálu middlewaru je stejně jednoduché jako přidání jednoho přírůstkového kódu k tomu, co již máte při použití IHttpClientFactory.

Jediným doplněním kódu použitého pro opakování volání HTTP je kód, do kterého přidáte zásadu Circuit Breaker do seznamu zásad k použití, jak je znázorněno v následujícím kódu.

// Program.cs
var retryPolicy = GetRetryPolicy();
var circuitBreakerPolicy = GetCircuitBreakerPolicy();

builder.Services.AddHttpClient<IBasketService, BasketService>()
        .SetHandlerLifetime(TimeSpan.FromMinutes(5))  // Sample: default lifetime is 2 minutes
        .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
        .AddPolicyHandler(retryPolicy)
        .AddPolicyHandler(circuitBreakerPolicy);

Metoda AddPolicyHandler() je to, co přidává zásady k HttpClient objektům, které použijete. V tomto případě se přidává strategie Polly pro obvodový přerušovač.

Pokud chcete mít modulární přístup, Politika obvodového jističe je definována v samostatné metodě nazvané GetCircuitBreakerPolicy(), jak je znázorněno v následujícím kódu:

// also in Program.cs
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}

V příkladu kódu výše je politika jističe nakonfigurovaná tak, aby přerušila nebo otevřela okruh, pokud se během opakování pěti po sobě jdoucích požadavků HTTP objeví chyby. Když k tomu dojde, obvod se přeruší po dobu 30 sekund: v daném období se volání okamžitě zablokují jističem, místo aby se skutečně uskutečnily. Zásada automaticky interpretuje relevantní výjimky a stavové kódy HTTP jako chyby.

Jističe by se také měly použít k přesměrování požadavků na záložní infrastrukturu, pokud jste měli problémy s konkrétním prostředkem nasazeným v jiném prostředí než klientská aplikace nebo služba, která provádí volání HTTP. Pokud dojde k výpadku v datacentru, které ovlivní jenom vaše back-endové mikroslužby, ale ne klientské aplikace, můžou se klientské aplikace přesměrovat na náhradní služby. Polly plánuje novou politiku automatizace scénáře zásad převzetí služeb při selhání.

Všechny tyto funkce jsou určené pro případy, kdy aktivně spravujete převzetí služeb při selhání v rámci kódu .NET, na rozdíl od automatického spravování Azure, které zajišťuje transparentnost umístění.

Z hlediska použití není nutné při použití HttpClient přidat nic nového, protože kód je stejný jako při použití HttpClient s IHttpClientFactory, jak je znázorněno v předchozích částech.

Testování opakovaných pokusů HTTP a jističů v eShopOnContainers

Kdykoli spustíte řešení eShopOnContainers v hostiteli Dockeru, musí spustit více kontejnerů. Některé kontejnery se spouštějí a inicializují pomaleji, například kontejner SQL Serveru. To platí zejména při prvním nasazení aplikace eShopOnContainers do Dockeru, protože potřebuje nastavit image a databázi. Skutečnost, že některé kontejnery začínají pomaleji než jiné, může způsobit, že ostatní služby zpočátku vyvolají výjimky HTTP, i když nastavíte závislosti mezi kontejnery na úrovni docker-compose, jak je vysvětleno v předchozích částech. Tyto závislosti v rámci Docker Compose mezi kontejnery jsou pouze na úrovni procesu. Proces vstupního bodu kontejneru se může spustit, ale SQL Server nemusí být připravený na dotazy. Výsledkem může být kaskádová chyba a aplikace může získat výjimku při pokusu o využití tohoto konkrétního kontejneru.

Tento typ chyby se může zobrazit také při spuštění, když se aplikace nasazuje do cloudu. V takovém případě můžou orchestrátory přesouvat kontejnery z jednoho uzlu nebo virtuálního počítače do jiného (tj. spouštění nových instancí) při vyrovnávání počtu kontejnerů v uzlech clusteru.

Způsob, jakým eShopOnContainers tyto problémy řeší při spouštění všech kontejnerů, je použití vzorku opakování, jak bylo dříve ilustrováno.

Otestování jističe v eShopOnContainers

Existuje několik způsobů, jak přerušit nebo otevřít okruh a otestovat ho pomocí eShopOnContainers.

Jednou z možností je snížit povolený počet opakování na 1 v zásadách jističe a znovu nasadit celé řešení do Dockeru. Při jednom opakování existuje dobrá šance, že požadavek HTTP během nasazení selže, otevře se jistič a zobrazí se chyba.

Další možností je použít vlastní middleware implementovaný v mikroslužbě Košíku . Pokud je tento middleware povolený, zachytí všechny požadavky HTTP a vrátí stavový kód 500. Middleware můžete povolit tak, že na identifikátor URI který selhává pošlete požadavek GET, například takto:

  • GET http://localhost:5103/failing
    Tento požadavek vrátí aktuální stav middlewaru. Pokud je middleware povolený, vrátí žádost stavový kód 500. Pokud je middleware zakázaný, neexistuje žádná odpověď.

  • GET http://localhost:5103/failing?enable
    Tento požadavek povolí middleware.

  • GET http://localhost:5103/failing?disable
    Tento požadavek zakáže middleware.

Například po spuštění aplikace můžete middleware povolit tak, že v libovolném prohlížeči vytvoříte požadavek pomocí následujícího identifikátoru URI. Upozorňujeme, že mikroslužba pro objednávky používá port 5103.

http://localhost:5103/failing?enable

Stav pak můžete zkontrolovat pomocí identifikátoru URI http://localhost:5103/failing, jak je znázorněno na obrázku 8-5.

Snímek obrazovky s kontrolou stavu neúspěšné simulace middlewaru

Obrázek 8–5 Kontrola stavu middleware "Failing" v ASP.NET – v tomto případě je neaktivní.

V tomto okamžiku mikroslužba Košík odpoví stavovým kódem 500 při každém volání.

Po spuštění middlewaru můžete zkusit vytvořit objednávku z webové aplikace MVC. Protože požadavky selžou, okruh se otevře.

V následujícím příkladu vidíte, že webová aplikace MVC má v logice blok catch pro umístění objednávky. Pokud kód zachytí výjimku otevřeného okruhu, zobrazí uživateli přívětivou zprávu s žádostí, aby počkal.

public class CartController : Controller
{
    //…
    public async Task<IActionResult> Index()
    {
        try
        {
            var user = _appUserParser.Parse(HttpContext.User);
            //Http requests using the Typed Client (Service Agent)
            var vm = await _basketSvc.GetBasket(user);
            return View(vm);
        }
        catch (BrokenCircuitException)
        {
            // Catches error when Basket.api is in circuit-opened mode
            HandleBrokenCircuitException();
        }
        return View();
    }

    private void HandleBrokenCircuitException()
    {
        TempData["BasketInoperativeMsg"] = "Basket Service is inoperative, please try later on. (Business message due to Circuit-Breaker)";
    }
}

Tady je souhrn. Politika opakování se několikrát pokusí odeslat požadavek HTTP a zachytí chyby HTTP. Když počet opakování dosáhne maximálního počtu nastaveného pro politiku obvodového přerušovače (v tomto případě 5), aplikace vyvolá výjimku BrokenCircuitException. Výsledkem je přátelská zpráva, jak je znázorněno na obrázku 8-6.

Snímek obrazovky webové aplikace MVC s nefunkční chybou služby košíku

Obrázek 8-6 Jistič vracející chybu do uživatelského rozhraní

Pro otevření nebo přerušení okruhu můžete implementovat jinou logiku. Nebo můžete zkusit požadavek HTTP na jinou back-endovou mikroslužbu, pokud existuje záložní datacentrum nebo redundantní back-endový systém.

A konečně, další možnost pro CircuitBreakerPolicy je použít Isolate (který otevře a udržuje okruh otevřený) a Reset (který ho znovu uzavře). Ty se dají použít k vytvoření užitečného HTTP koncového bodu, který přímo na zásadách vyvolává Isolate a Reset. Takový koncový bod HTTP lze také použít, vhodně zabezpečený, v produkčním prostředí pro dočasné izolování podřízeného systému, například když ho chcete upgradovat. Nebo můžete obvod ručně vypnout, aby se chránil následný systém, u něhož máte podezření na poruchu.

Dodatečné zdroje