Aracılığıyla paylaş


Devre Kesici desenini uygulama

Tavsiye

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

.NET Mikro Hizmetler Mimarisi Kapsayıcılı .NET Uygulamaları için eKitabın kapak küçük resmi .

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 hizmete yönelik trafiğin üstel olarak artmasıyla tehlikeli bir risk 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.

IHttpClientFactory ve Polly ile Devre Kesici desenini uygula

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

Ara yazılım çıktı işlem hattınıza IHttpClientFactory devre kesici prensibi eklemek, IHttpClientFactory kullanırken mevcut koda basit bir ekleme yapmak kadar kolaydır.

HTTP çağrısı yeniden denemeleri için kullanılan koda yapılan tek ekleme, Devre Kesici ilkesini kullanılacak ilkeler listesine ekleme kodudur ve bu, aşağıdaki aşamalı kodda gösterilmektedir.

// 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, HttpClient nesnelerine kullanacağınız ilkeleri ekler. 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 yapılmayacak şekilde devre kesici tarafından hemen başarısız sayılır. İ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 kesinti yönetimi senaryosunu otomatikleştirmek için yeni bir politika oluşturmayı planlıyor.

Bu özellikler, Azure tarafından konum şeffaflığı ile otomatik olarak yönetilen durumlar yerine, yük devretme yönetimini .NET kodunun içinden yönettiğiniz durumlar için tasarlanmıştır.

HttpClient kullanılırken, önceki bölümlerde gösterildiği gibi, HttpClient ile IHttpClientFactory birlikte kullanıldığında olduğu gibi kod aynı olduğu için buraya yeni bir şey eklemenize gerek yoktur.

eShopOnContainers'da HTTP yeniden denemelerini ve devre kesici mekanizmalarını test edin

eShopOnContainers çözümünü bir Docker konakında başlattığınızda, birden çok kapsayıcının başlatılması 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ç bir hata zinciri olabilir ve uygulama belirli kapsayıcıyı tüketmeye çalışırken hata 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 arasındaki kapsayıcı sayısını dengelemek için kapsayıcıları bir düğümden veya VM'den diğerine taşıyor olabilirler, yani yeni örnekler başlatarak.

'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.

Başarısız ara yazılım benzetiminin durumunu denetleme işleminin ekran görüntüsü.

Ş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, Sepet mikro hizmetini her çağırdığınızda 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 devre 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 istisnasını yakalarsa, kullanıcıya beklemesini söyleyen samimi bir mesaj 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 bir özet. 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 samimi bir mesajdır.

Sepet hizmeti çalışmama hatasıyla MVC web uygulamasının ekran görüntüsü.

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

Bağlantı hattının ne zaman açıldığında/kesildiğinde farklı mantık uygulayabilirsiniz. Alternatif olarak, bir geri dönüş veri merkezi veya yedek arka uç sistem varsa, farklı bir arka uç mikroservise karşı bir HTTP isteği deneyebilirsiniz.

Son olarak, CircuitBreakerPolicy için başka bir olasılık, devreyi açıp açık tutan Isolate'i ve tekrar kapatmak için Reset'yi kullanmaktır. Bunlar, ilkede Yalıtma ve Sıfırlama işlemlerini doğrudan çağıran bir yardımcı 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 manuel olarak kesebilirsiniz.

Ek kaynaklar