Megosztás a következőn keresztül:


Az áramkör-megszakító minta implementálása

Jótanács

Ez a tartalom egy részlet a '.NET Microservices Architecture for Containerized .NET Applications' című eBook-ból, amely elérhető a .NET Docs oldalon, vagy ingyenesen letölthető PDF formátumban, amely offline módban is olvasható.

.NET mikroszolgáltatások architektúrája konténerizált .NET alkalmazásokhoz e-könyv borító miniatűr.

Ahogy korábban már említettük, olyan hibákat kell kezelnie, amelyek helyreállítása változó ideig tarthat, ahogy az is előfordulhat, amikor távoli szolgáltatáshoz vagy erőforráshoz próbál csatlakozni. Az ilyen típusú hibák kezelése javíthatja az alkalmazások stabilitását és rugalmasságát.

Elosztott környezetben a távoli erőforrásokra és szolgáltatásokra irányuló hívások átmeneti hibák, például lassú hálózati kapcsolatok és időtúllépések miatt meghiúsulhatnak, vagy ha az erőforrások lassan válaszolnak, vagy átmenetileg nem érhetők el. Ezek a hibák általában rövid idő után kijavítják magukat, és egy robusztus felhőalkalmazásnak fel kell készülnie arra, hogy kezelni tudja őket egy olyan stratégiával, mint az "Újrapróbálkozási minta".

Lehetnek azonban olyan helyzetek is, amikor a hibák olyan váratlan események miatt keletkeznek, amelyek kijavítása hosszabb időt vehet igénybe. Az ilyen hibák súlyossága a részleges kapcsolódási problémától a szolgáltatás teljes leállásáig terjedhet. Ilyen helyzetekben értelmetlen lehet, ha egy alkalmazás folyamatosan újrapróbálkozott egy olyan művelettel, amely nem valószínű, hogy sikeres lesz.

Ehelyett az alkalmazást kódolva kell elfogadni, hogy a művelet meghiúsult, és ennek megfelelően kezelje a hibát.

A Http-újrapróbálkozások gondtalan használata szolgáltatásmegtagadási (DoS-) támadást eredményezhet a saját szoftverén belül. Ha egy mikroszolgáltatás meghiúsul vagy lassan teljesít, több ügyfél is újrapróbálkozott a sikertelen kérelmekkel. Ez veszélyes kockázatot jelent, ha exponenciálisan növeli a meghibásodott szolgáltatásra irányuló forgalmat.

Ezért szüksége van valamilyen védelmi gátra, hogy a túlzott kérések leálljanak, amikor nem érdemes tovább próbálkozni. Az a védőgát pontosan az áramkör megszakító.

Az áramkör-megszakító mintának más célja van, mint az "Újrapróbálkozási minta". Az "Újrapróbálkozási minta" lehetővé teszi, hogy az alkalmazás újrapróbálkozjon egy műveletet abban a reményben, hogy a művelet végül sikeres lesz. Az áramkör-megszakító minta megakadályozza, hogy egy alkalmazás olyan műveletet hajtson végre, amely valószínűleg sikertelen lesz. Az alkalmazások kombinálhatják ezt a két mintát. Az újrapróbálkozási logikának azonban érzékenynek kell lennie az áramkör-megszakító által visszaadott kivételre, és fel kell hagynia az újrapróbálkozási kísérletekből, ha az áramkör-megszakító azt jelzi, hogy a hiba nem átmeneti.

Áramkör-megszakító minta megvalósítása IHttpClientFactory és Polly segítségével

Ahogyan a visszaküldések implementálásakor, a körmegszakítók ajánlott megközelítése az olyan bevált .NET-kódtárak kihasználása, mint a Polly és a IHttpClientFactory-vel való natív integráció.

Az áramkör-megszakító szabály hozzáadása a IHttpClientFactory kimenő middleware folyamatához olyan egyszerű, mintha csak egy új kódrészletet adna hozzá a IHttpClientFactory használatakor.

A HTTP-hívások újrapróbálkozásához használt kódban csak az a módosított kód található meg, amelyben hozzáadja a Circuit Breaker szabályzatot a használandó szabályzatok listájához, ahogyan az az alábbi módosított kódban is látható.

// 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);

Ez a módszer az, amely hozzáadja a szabályzatokat az általad használni kívánt AddPolicyHandler() objektumokhoz HttpClient. Ebben az esetben polly szabályzatot ad hozzá egy áramkör-megszakítóhoz.

A moduláris megközelítés érdekében a Circuit Breaker Policy egy külön eljárásban van meghatározva, ahogyan azt a következő kód mutatja.

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

A fenti kód példában a megszakító házirend úgy van konfigurálva, hogy megszakítsa vagy megnyissa a kapcsolatcsoportot, amikor a Http-kérések újrapróbálásakor öt egymást követő hiba történt. Amikor ez történik, az áramkör 30 másodpercig megszakad: ebben az időszakban a hívásokat a megszakító azonnal leállítja, nem pedig ténylegesen kerülnek elhelyezésre. A szabályzat automatikusan hibaként értelmezi a releváns kivételeket és a HTTP-állapotkódokat .

A kapcsolatcsoport-megszakítókat arra is érdemes használni, hogy a kérelmeket tartalék infrastruktúrára irányítsák át, ha egy olyan erőforrással kapcsolatos probléma merült fel, amely más környezetben van üzembe helyezve, mint a HTTP-hívást végrehajtó ügyfélalkalmazás vagy szolgáltatás. Így ha az adatközpontban olyan kimaradás történik, amely csak a háttérbeli mikroszolgáltatásokat érinti, az ügyfélalkalmazásokat azonban nem, az ügyfélalkalmazások átirányíthatják a tartalék szolgáltatásokra. A Polly egy új szabályzatot tervez a feladatátvételi szabályzat forgatókönyvének automatizálásához.

Ezek a funkciók olyan esetekre szolgálnak, amikor a feladatátvételt a .NET-kódból kezeli, nem pedig automatikusan az Azure-ban, a hely átláthatóságával.

Használat szempontjából a HttpClient használatakor itt nem kell újat hozzáadni, mert a kód ugyanaz, mint a korábbi HttpClientIHttpClientFactoryszakaszokban látható.

Http újrapróbálkozások és áramkör-megszakítók tesztelése az eShopOnContainersben

Amikor elindítja az eShopOnContainers megoldást egy Docker-gazdagépen, több tárolót kell elindítania. Egyes tárolók indítása és inicializálása lassabb, például az SQL Server-tároló. Ez különösen igaz az eShopOnContainers alkalmazás Dockerben való első üzembe helyezésére, mert be kell állítania a rendszerképeket és az adatbázist. Az a tény, hogy egyes tárolók lassabban indulnak el, mint mások, a többi szolgáltatás kezdetben HTTP-kivételeket okozhat, még akkor is, ha docker-compose szinten állítja be a tárolók közötti függőségeket, ahogyan azt az előző szakaszokban ismertetjük. A tárolók közötti docker-compose függőségek csak a folyamat szintjén vannak. A tároló belépési pontjának folyamata elindítható, de előfordulhat, hogy az SQL Server nem áll készen a lekérdezésekre. Az eredmény több hiba kaszkádja lehet, és az alkalmazás kivételt kaphat az adott tároló használata során.

Az ilyen típusú hibák indításkor is megjelenhetnek, amikor az alkalmazás üzembe helyezése a felhőben történik. Ebben az esetben előfordulhat, hogy az orchestrátorok tárolókat helyeznek át egyik csomópontról vagy virtuális gépről a másikra (vagyis új példányokat indítanak) a tárolók számának a fürt csomópontjai közötti kiegyensúlyozásakor.

Az "eShopOnContainers" a korábban bemutatott Újrapróbálkozási minta használatával oldja meg ezeket a problémákat az összes tároló indításakor.

Az áramkör-megszakító tesztelése az eShopOnContainersben

Az áramkör megszakításának/meggyógyításának számos módja van, és tesztelheti az eShopOnContainers segítségével.

Az egyik lehetőség az, hogy az újrapróbálkozések engedélyezett számát 1-re csökkenti az áramkör-megszakító házirendben, és újra üzembe helyezi a teljes megoldást a Dockerben. Egyetlen újrapróbálkozással jó esély van arra, hogy egy HTTP-kérés sikertelen lesz az üzembe helyezés során, megnyílik az áramkör-megszakító, és hibaüzenet jelenik meg.

Egy másik lehetőség a Basket mikroszolgáltatásban implementált egyéni köztes szoftver használata. Ha ez a köztes szoftver engedélyezve van, az összes HTTP-kérést elfogja, és az 500-os állapotkódot adja vissza. A köztes szoftver engedélyezéséhez get kérést kell küldenie a sikertelen URI-hoz, például az alábbiak szerint:

  • GET http://localhost:5103/failing
    Ez a kérés a köztes szoftver aktuális állapotát adja vissza. Ha a köztes szoftver engedélyezve van, a kérés az 500-os állapotkódot adja vissza. Ha a köztes szoftver le van tiltva, nincs válasz.

  • GET http://localhost:5103/failing?enable
    Ez a kérés engedélyezi a köztes szoftvereket.

  • GET http://localhost:5103/failing?disable
    Ez a kérés letiltja a köztes szoftvereket.

Ha például az alkalmazás fut, engedélyezheti a köztes szoftvereket a következő URI használatával bármely böngészőben. Vegye figyelembe, hogy a rendelési mikroszolgáltatás az 5103-at használja.

http://localhost:5103/failing?enable

Ezután az URI http://localhost:5103/failinghasználatával ellenőrizheti az állapotot, ahogy a 8–5. ábrán látható.

Képernyőkép a hibás köztes szoftveres szimuláció állapotának ellenőrzéséről.

8-5. ábra. A "Sikertelen" ASP.NET köztes szoftver állapotának ellenőrzése – Ebben az esetben le van tiltva.

Ekkor a Basket mikroszolgáltatás 500-os állapotkóddal válaszol, amikor meghívja.

A köztes szoftver futtatása után megpróbálhat rendelést készíteni az MVC webalkalmazásból. Mivel a kérések sikertelenek, a kapcsolatcsoport megnyílik.

Az alábbi példában láthatja, hogy az MVC webalkalmazás logikájában található egy hibakezelő blokk a megrendelés leadására. Ha a kód egy nyitott áramköri kivételt kap, a felhasználónak egy rövid üzenet jelenik meg, amely arra utasítja őket, hogy várjanak.

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)";
    }
}

Íme egy összegzés. Az Újrapróbálkozás szabályzat többször is megpróbál HTTP-kérést küldeni, és HTTP-hibákat kap. Amikor az újrapróbálkozások száma eléri a megszakító politika számára beállított maximális számot (ebben az esetben 5), az alkalmazás BrokenCircuitException kivételt dob. Az eredmény egy barátságos üzenet, ahogyan a 8-6. ábrán látható.

Képernyőkép az MVC webalkalmazásról, ahol a kosár szolgáltatás működésképtelen állapotban van.

8-6. ábra. Az áramkör-megszakító hibát ad vissza a felhasználói felületnek

Az áramkör megnyitásának vagy megszakításának különböző logikáját implementálhatja. Ha tartalék adatközpontot vagy redundáns háttérrendszert használ, megpróbálhat HTTP-kérést egy másik háttérbeli mikroszolgáltatással.

Végül, egy másik lehetőség a CircuitBreakerPolicy használata a Isolate (amely nyitva tartja az áramkört) és Reset (amely újra bezárja). Ezekkel létrehozhat egy hasznosításra szánt HTTP-végpontot, amely közvetlenül a szabályzaton hívja meg az elkülönítési és az alaphelyzetbe állítási műveleteket. Az ilyen HTTP-végpontok éles környezetben is használhatók, megfelelően védve egy alsóbb rétegbeli rendszer ideiglenes elkülönítéséhez, például a frissítéshez. Vagy manuálisan is meg lehet rántni a kapcsolatcsoportot, hogy megvédje a hibásnak vélt alsóbb rétegbeli rendszert.

További erőforrások