Yeniden deneme fırtınası kötü modeli

Bir hizmet kullanılamıyor veya meşgul olduğunda, istemcilerin bağlantılarını çok sık yeniden denemesini sağlamak hizmetin kurtarılmasına ve sorunun daha kötü olmasına neden olabilir. Ayrıca, istekler genellikle tanımlı bir süre için geçerli olduğundan, sonsuza kadar yeniden denenmez.

Sorun açıklaması

Bulutta hizmetler bazen sorunlar yaşar ve istemciler için kullanılamaz hale gelir ya da istemcilerini sınırlamak veya derecelendirmek zorunda kalabilir. İstemcilerin hizmetlere yönelik başarısız bağlantıları yeniden denemesi iyi bir uygulamadır, ancak çok sık yeniden denememelidir veya çok uzun süredir. Hizmetler büyük olasılıkla kurtarılamamış olduğundan, kısa bir süre içinde yeniden denemeler başarısız olur. Ayrıca hizmetler, kurtarmaya çalışırken çok sayıda bağlantı girişimi yapıldığında daha da fazla yük alabilir ve yinelenen bağlantı denemeleri hizmeti önemli bir şekilde gösterebilir ve temel sorunu kötüleşir.

Aşağıdaki örnek, bir istemcinin sunucu tabanlı bir API 'ye bağlandığı bir senaryoyu gösterir. İstek başarılı olmazsa, istemci hemen yeniden dener ve sonsuza kadar yeniden denemeye devam eder. Genellikle bu davranış sıralaması bu örnekteki değerden daha hafif olur, ancak aynı ilke geçerlidir.

public async Task<string> GetDataFromServer()
{
    while(true)
    {
        var result = await httpClient.GetAsync(string.Format("http://{0}:8080/api/...", hostName));
        if (result.IsSuccessStatusCode) break;
    }

    // ... Process result.
}

Sorunun çözümü

İstemci uygulamaları, yeniden deneme fırtınası ile karşılaşmamak için bazı en iyi yöntemleri izlemelidir.

  • Yeniden deneme girişimlerinin sayısı üst sınırı ve uzun bir süre yeniden denenmeyin. Bir döngü yazmak kolay görünse while(true) de, başlatılmakta olan istek nedeniyle büyük bir süre boyunca gerçekten yeniden denemek istemezsiniz. bu yana, başlatılan isteği gösteren durum muhtemelen değişmiş olabilir. Çoğu uygulamada birkaç saniye veya dakika için yeniden deneme yeterlidir.
  • Yeniden deneme girişimleri arasında duraklatın. Bir hizmet kullanılamaz durumdaysa, hemen yeniden denenmenin başarılı olması düşüktür. Denemeler arasında beklenecek süreyi, örneğin bir üstel geri alma stratejisikullanarak kademeli olarak artırın.
  • Hataları sorunsuz bir şekilde işler. Hizmet yanıt vermiyorsa, denemesi iptal edilip edilmeyeceğini göz önünde bulundurun ve Kullanıcı veya bileşeninizin çağıranına geri dönüp bir hata döndürür. Uygulamanızı tasarlarken bu başarısızlık senaryolarını göz önünde bulundurun.
  • Özellikle yeniden deneme Storms ' i önlemeye yardımcı olmak için tasarlanan devre kesici modelinikullanmayı düşünün.
  • Sunucu bir retry-after yanıt üst bilgisi sağlıyorsa, belirtilen zaman aralığı bitene kadar yeniden denemeye çalışmayın emin olun.
  • Azure hizmetleriyle iletişim kurarken resmi SDK 'Ları kullanın. Bu SDK 'lar genellikle, bir veya yeniden deneme Storms 'e katkıda bulunmak için yerleşik yeniden deneme ilkelerine ve korumalarına sahiptir. SDK 'sı olmayan veya SDK 'nın yeniden deneme mantığını doğru bir şekilde işleyemeyen bir hizmetle iletişim ediyorsanız, yeniden deneme mantığınızı doğru şekilde işlemek ve kodu yazmak zorunda kalmamak için, Polly (.NET için) veya retry (JavaScript için) gibi bir kitaplık kullanmayı deneyin.
  • Bunu destekleyen bir ortamda çalıştırıyorsanız, giden çağrıları göndermek için bir hizmet ağı (veya başka bir soyutlama katmanı) kullanın. Genellikle, Davprgibi bu araçlar yeniden deneme ilkelerini destekler ve yinelenen girişimlerin ardından kapatma gibi en iyi uygulamaları otomatik olarak izler. Bu yaklaşım, yeniden deneme kodu yazmanız gerekmediği anlamına gelir.
  • İstekleri toplu işleme ve kullanılabilir olduğunda istek havuzunu kullanmayı göz önünde bulundurun. Birçok SDK isteği, sizin adınıza istek toplu işlem ve bağlantı havuzu oluşturma işlemini gerçekleştirir, ancak yine de bu bağlantıları çok sık yeniden denememeye gerek kalmaz.

Hizmetler Ayrıca, yeniden deneme Storms 'leri için kendilerini korumalıdır.

  • Bir olay sırasında bağlantıları kapatabilmeniz için bir ağ geçidi katmanı ekleyin. Bu, Bulkbaş desenininbir örneğidir. Azure, ön kapı, Application Gatewayve API Managementdahil farklı türlerde çözümler için birçok farklı ağ geçidi hizmeti sağlar.
  • Ağ geçidinizdeki istekleri kısıtlama. Bu, arka uç bileşenlerinizin çalışmaya devam edemeyeceği çok sayıda isteği kabul etmemesini sağlar.
  • Daraltma yapıyorsanız, retry-after istemcilerin bağlantılarının ne zaman yeniden gönderileceğini anlamalarına yardımcı olmak için bir üst bilgi gönderin.

Dikkat edilmesi gerekenler

  • İstemciler döndürülen hata türünü göz önünde bulundurmalıdır. Bazı hata türleri hizmette hata göstermez, bunun yerine istemcinin geçersiz bir istek gönderdiğini gösterir. Örneğin, bir istemci uygulaması bir 400 Bad Request hata yanıtı alırsa, sunucu isteğinizin geçerli olmadığını söylediğinden, aynı isteğin de yeniden denenmesinden kaynaklanıyor olabilir.
  • İstemciler, yeniden bağlantı bağlantıları için anlamlı olan sürenin uzunluğunu göz önünde bulundurmalıdır. Yeniden denemeniz gereken sürenin uzunluğu iş gereksinimlerinize göre ve bir hatayı bir kullanıcıya veya çağırana geri yaymaya makul bir şekilde yayıp yayamayacağını belirtir. Çoğu uygulamada birkaç saniye veya dakika için yeniden deneme yeterlidir.

Sorunu algılama

Bir istemcinin perspektifinden, bu sorunun belirtileri çok uzun yanıt veya işleme süreleri içerebilir ve bu da bağlantıyı yeniden denemeye yönelik yinelenen girişimleri gösteren telemetriyle birlikte olabilir.

Hizmetin perspektifinden, bu sorunun belirtileri kısa bir süre içinde bir istemciden çok sayıda istek ya da kesintiden kurtarılırken tek bir istemciden çok sayıda istek içerebilir. Belirtiler, hizmeti kurtarırken veya bir hata onarıldıktan sonra hizmetin devam eden hatalarla karşılaşmakta güçlük de içerebilir.

Örnek tanılama

Aşağıdaki bölümlerde, hem istemci tarafında hem de hizmet tarafında olası bir yeniden deneme fırtınası algılaması için bir yaklaşım gösterilmektedir.

İstemci telemetrisinden tanımlama

Azure Application Insights , uygulamalardan telemetri kaydeder ve verileri sorgulama ve görselleştirme için kullanılabilir hale getirir. Giden bağlantılar bağımlılıklar olarak izlenir ve bunlarla ilgili bilgilere, bir istemcinin aynı hizmete çok sayıda giden istek ne zaman bir istek yapıp yapacağına ilişkin bilgiler erişilebilir.

aşağıdaki grafik Application Insights portalı içindeki ölçümler sekmesinden alınmıştır ve uzak bağımlılık adınagöre bölünmüş bağımlılık arızaları ölçüsünü görüntülüyor. Bu, kısa bir süre içinde bağımlılığı başarısız bağlantı denemelerinde oluşan (21.000 üzerinde) büyük bir senaryoyu gösterir.

30 dakikalık dönemdeki tek bir bağımlılığa 21k bağımlılık başarısızlıklarını gösteren Application Insights ekran görüntüsü

Sunucu telemetrisinden tanımlama

Sunucu uygulamaları tek bir istemciden çok sayıda bağlantıyı algılayabiliyor olabilir. Aşağıdaki örnekte, Azure ön kapısı bir uygulama için bir ağ geçidi görevi görür ve tüm istekleri Log Analytics çalışma alanına kaydetmek üzere yapılandırılmıştır .

Aşağıdaki kusto sorgusu Log Analytics karşı yürütülebilir. Son gün içinde uygulamaya çok sayıda istek gönderen istemci IP adreslerini tanımlayacaktır.

AzureDiagnostics
| where ResourceType == "FRONTDOORS" and Category == "FrontdoorAccessLog"
| where TimeGenerated > ago(1d)
| summarize count() by bin(TimeGenerated, 1h), clientIp_s
| order by count_ desc

Yeniden deneme sırasında bu sorguyu yürütmek, tek bir IP adresinden çok sayıda bağlantı girişimini gösterir.

Bir saatlik dönem içindeki tek bir IP adresinden ön kapıya 81.608 gelen bağlantıyı gösteren Log Analytics ekran görüntüsü