Devre Kesici desenini uygulama

İpucu

Bu içerik, .NET Docs'ta veya çevrimdışı olarak okunabilen ücretsiz indirilebilir bir PDF olarak sağlanan Kapsayıcılı .NET Uygulamaları için .NET Mikro Hizmet Mimarisi e-Kitabı'ndan bir alıntıdır.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Daha önce belirtildiği gibi, uzak bir hizmete veya kaynağa bağlanmaya çalıştığınızda gerçekleşebileceği gibi, kurtarılması çok uzun sürebilecek hataları işlemeniz gerekir. Bu tür hataların işlenmesi, bir uygulamanın kararlılığını ve dayanıklılığını artırabilir.

Dağıtılmış bir ortamda, uzak kaynaklara ve hizmetlere yapılan çağrılar, yavaş ağ bağlantıları ve zaman aşımları gibi geçici hatalardan veya kaynakların yavaş yanıt vermesi veya geçici olarak kullanılamaması nedeniyle başarısız olabilir. Bu hatalar genellikle kısa bir süre sonra kendilerini düzeltir ve "Yeniden Deneme düzeni" gibi bir strateji kullanılarak sağlam bir bulut uygulaması bunları işlemeye hazır olmalıdır.

Ancak hataların düzeltilmesi çok daha uzun sürebilecek, tahmin edilmeyen olaylardan kaynaklandığı durumlar da olabilir. Bu hataların önem derecesi kısmi bağlantı kaybıyla bir hizmetin tamamen çökmesi arasında değişebilir. Bu gibi durumlarda, bir uygulamanın başarılı olma olasılığı düşük bir işlemi sürekli olarak yeniden denemesi anlamsız olabilir.

Bunun yerine uygulama, işlemin başarısız olduğunu kabul etmek ve hatayı uygun şekilde işlemek için kodlanmalıdır.

Http yeniden denemelerini dikkatsizce kullanmak, kendi yazılımınızda Hizmet Reddi (DoS) saldırısı oluşturulmasına neden olabilir. Mikro hizmet başarısız olduğunda veya yavaş bir performans sergileyebileceğinden, birden çok istemci başarısız istekleri tekrar tekrar yeniden deneyebilir. Bu, başarısız hizmeti hedefleyen trafiği üstel olarak artırma riski oluşturur.

Bu nedenle, denemeye devam etmeye değmeyen aşırı isteklerin durması için bir tür savunma engeline ihtiyacınız vardır. Bu savunma bariyeri tam olarak devre kesici.

Devre Kesici düzeninin amacı "Yeniden Deneme düzeni"den farklıdır. "Yeniden deneme düzeni", bir uygulamanın işlemin sonunda başarılı olacağı beklentisi içinde bir işlemi yeniden denemesini sağlar. Devre Kesici düzeni, uygulamanın başarısız olma olasılığı olan bir işlem gerçekleştirmesini engeller. Bir uygulama bu iki deseni birleştirebilir. Ancak, yeniden deneme mantığı devre kesici tarafından döndürülen özel durumlara duyarlı olmalıdır ve devre kesici bir hatanın geçici olmadığını belirtiyorsa yeniden deneme girişimlerini bırakmalıdır.

ve Polly ile IHttpClientFactory Devre Kesici deseni uygulama

Yeniden denemeleri uygularken olduğu gibi, devre kesiciler için önerilen yaklaşım Polly ve ile IHttpClientFactoryyerel tümleştirmesi gibi kanıtlanmış .NET kitaplıklarından yararlanmaktır.

Giden ara yazılım işlem hattınıza IHttpClientFactory devre kesici ilkesi eklemek, kullanırken IHttpClientFactorysahip olduğunuz koda tek bir artımlı kod eklemek kadar basittir.

HTTP çağrısı yeniden denemeleri için kullanılan koda buradaki tek ek, aşağıdaki artımlı kodda gösterildiği gibi Devre Kesici ilkesini kullanılacak ilkeler listesine eklediğiniz koddur.

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

AddPolicyHandler() yöntemi, kullanacağınız nesnelere HttpClient ilke ekleyen yöntemdir. Bu durumda, devre kesici için bir Polly ilkesi ekleniyor.

Daha modüler bir yaklaşıma sahip olmak için Devre Kesici İlkesi, aşağıdaki kodda gösterildiği gibi adlı GetCircuitBreakerPolicy()ayrı bir yöntemde tanımlanır:

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

Yukarıdaki kod örneğinde devre kesici ilkesi, Http isteklerini yeniden denerken ardışık beş hata olduğunda devreyi bozacak veya açacak şekilde yapılandırılır. Böyle bir durumda, devre 30 saniye süreyle kesilir: bu süre içinde, çağrılar gerçekten yerleştirilmeyecek şekilde devre kesici tarafından hemen başarısız olur. İlke, ilgili özel durumları ve HTTP durum kodlarını otomatik olarak hata olarak yorumlar.

Http çağrısını gerçekleştiren istemci uygulama veya hizmetten farklı bir ortamda dağıtılan belirli bir kaynakta sorun yaşıyorsanız, devre kesiciler istekleri bir geri dönüş altyapısına yeniden yönlendirmek için de kullanılmalıdır. Bu şekilde, veri merkezinde yalnızca arka uç mikro hizmetlerinizi etkileyen ancak istemci uygulamalarınızı etkilemeyen bir kesinti varsa, istemci uygulamaları geri dönüş hizmetlerine yönlendirebilir. Polly, bu yük devretme ilkesi senaryosunu otomatikleştirmek için yeni bir ilke planlıyor.

Tüm bu özellikler, yük devretmeyi Azure tarafından sizin için otomatik olarak yönetilmeye değil, konum saydamlığıyla .NET kodunun içinden yönettiğiniz durumlara yöneliktir.

Kullanım açısından, HttpClient kullanılırken, kod ile IHttpClientFactorykullanıldığından önceki bölümlerde gösterildiği gibi ile aynı HttpClient olduğundan buraya yeni bir şey eklemeniz gerekmez.

eShopOnContainers'da Http yeniden denemelerini ve devre kesicilerini test edin

eShopOnContainers çözümünü bir Docker konasında başlattığınızda, birden çok kapsayıcı başlatması gerekir. SQL Server kapsayıcısı gibi bazı kapsayıcıların başlatılması ve başlatılması daha yavaştır. Bu, özellikle eShopOnContainers uygulamasını Docker'a ilk kez dağıttığınızda geçerlidir çünkü görüntüleri ve veritabanını ayarlaması gerekir. Bazı kapsayıcıların diğerlerinden daha yavaş başlaması, önceki bölümlerde açıklandığı gibi docker-compose düzeyinde kapsayıcılar arasında bağımlılıklar ayarlasanız bile hizmetlerin geri kalanının başlangıçta HTTP özel durumları oluşturmasına neden olabilir. Kapsayıcılar arasındaki docker-compose bağımlılıkları yalnızca işlem düzeyindedir. Kapsayıcının giriş noktası işlemi başlatılabilir, ancak SQL Server sorgular için hazır olmayabilir. Sonuç art arda hatalar olabilir ve uygulama söz konusu kapsayıcıyı kullanmaya çalışırken bir özel durum alabilir.

Ayrıca, uygulama buluta dağıtılırken başlangıçta bu tür bir hata görebilirsiniz. Bu durumda, düzenleyiciler kümenin düğümleri genelindeki kapsayıcı sayısını dengelerken kapsayıcıları bir düğümden veya VM'den diğerine (yeni örnekler başlatırken) taşıyor olabilir.

'eShopOnContainers' tüm kapsayıcıları başlatırken bu sorunları çözmenin yolu, daha önce gösterilen Yeniden Deneme desenini kullanmaktır.

eShopOnContainers'da devre kesiciyi test edin

Devreyi açıp eShopOnContainers ile test etmenin birkaç yolu vardır.

Bir seçenek, devre kesici ilkesinde izin verilen yeniden deneme sayısını 1'e düşürmek ve çözümün tamamını Docker'a yeniden dağıtmaktır. Tek bir yeniden denemeyle, dağıtım sırasında bir HTTP isteğinin başarısız olma olasılığı yüksektir, devre kesici açılır ve bir hata alırsınız.

Bir diğer seçenek de Sepet mikro hizmette uygulanan özel ara yazılımı kullanmaktır. Bu ara yazılım etkinleştirildiğinde, tüm HTTP isteklerini yakalar ve 500 durum kodunu döndürür. Aşağıdaki gibi, başarısız URI'ye bir GET isteğinde bulunarak ara yazılımı etkinleştirebilirsiniz:

  • GET http://localhost:5103/failing
    Bu istek ara yazılımının geçerli durumunu döndürür. Ara yazılım etkinleştirilirse, istek durum kodu 500 döndürür. Ara yazılım devre dışı bırakılırsa yanıt olmaz.

  • GET http://localhost:5103/failing?enable
    Bu istek ara yazılımı etkinleştirir.

  • GET http://localhost:5103/failing?disable
    Bu istek ara yazılımı devre dışı bırakır.

Örneğin, uygulama çalıştırıldıktan sonra herhangi bir tarayıcıda aşağıdaki URI'yi kullanarak bir istekte bulunarak ara yazılımı etkinleştirebilirsiniz. Sipariş mikro hizmetinin 5103 numaralı bağlantı noktasını kullandığını unutmayın.

http://localhost:5103/failing?enable

Ardından, Şekil 8-5'te gösterildiği gibi URI'sini http://localhost:5103/failingkullanarak durumu de kontrol edebilirsiniz.

Screenshot of checking the status of failing middleware simulation.

Şekil 8-5. "Başarısız" ASP.NET ara yazılımının durumu denetleniyor – Bu durumda devre dışı bırakıldı.

Bu noktada, Her çağırdığınızda Sepet mikro hizmeti 500 durum koduyla yanıt verir.

Ara yazılım çalıştırıldıktan sonra MVC web uygulamasından sipariş almayı deneyebilirsiniz. İstekler başarısız olduğundan bağlantı hattı açılır.

Aşağıdaki örnekte, MVC web uygulamasının sipariş verme mantığında bir catch bloğu olduğunu görebilirsiniz. Kod bir açık devre özel durumu yakalarsa kullanıcıya beklemesini söyleyen kolay bir ileti gösterir.

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

İşte özeti. Yeniden Deneme ilkesi, HTTP isteğinde bulunmak için birkaç kez dener ve HTTP hataları alır. Yeniden deneme sayısı Devre Kesici ilkesi için ayarlanan en yüksek sayıya ulaştığında (bu örnekte, 5), uygulama bir BrokenCircuitException oluşturur. Sonuç, Şekil 8-6'da gösterildiği gibi kolay bir iletidir.

Screenshot of the MVC web app with basket service inoperative error.

Şekil 8-6. Devre kesici kullanıcı arabirimine hata döndürerek

Bağlantı hattının ne zaman açıldığında/kesildiğinde farklı mantık uygulayabilirsiniz. Alternatif olarak, geri dönüş veri merkezi veya yedekli arka uç sistemi varsa farklı bir arka uç mikro hizmeti için http isteği deneyebilirsiniz.

Son olarak, için başka bir olasılık CircuitBreakerPolicy kullanmaktır Isolate (açık ve açık devreyi tutar) ve Reset (tekrar kapatır). Bunlar, doğrudan ilkede Yalıt ve Sıfırla'yı çağıran bir yardımcı program HTTP uç noktası oluşturmak için kullanılabilir. Böyle bir HTTP uç noktası, yükseltme yapmak istediğiniz durumlar gibi bir aşağı akış sistemini geçici olarak yalıtmak için üretimde uygun şekilde güvenli hale getirilebilir. Ya da arızalı olduğundan şüphelendiğiniz bir aşağı akış sistemini korumak için devreyi el ile kullanabilir.

Ek kaynaklar