Aracılığıyla paylaş


Storm kötü amaçlı yazılımdan korumayı yeniden deneme

Bir hizmet kullanılamadığında veya meşgul olduğunda, istemcilerin bağlantılarını çok sık yeniden denemesi, hizmetin kurtarılma sorununa neden olabilir ve sorunu daha da kötüleştirebilir. İstekler genellikle yalnızca tanımlı bir süre için geçerli olduğundan, sonsuza kadar yeniden denemek de mantıklı değildir.

Sorun açıklaması

Bulutta, hizmetler bazen sorunlarla karşılaşır ve istemciler tarafından kullanılamaz duruma gelir ya da istemcilerini kısıtlamak veya hız sınırlaması yapmak zorunda kalır. İstemcilerin hizmetlerle başarısız bağlantıları yeniden denemesi iyi bir uygulama olsa da, çok sık veya çok uzun süre yeniden denememeleri önemlidir. Hizmetlerin muhtemelen henüz toparlanmamış olması nedeniyle, kısa süre içinde yeniden denemelerin başarılı olma olasılığı düşüktür. Ayrıca, kurtarmaya çalışırken çok fazla bağlantı girişimi yapıldığında hizmetler daha da strese girebilir ve yinelenen bağlantı girişimleri hizmeti bunaltabilir ve temel sorunu daha da kötüleştirebilir.

Aşağıdaki örnekte, istemcinin sunucu tabanlı API'ye bağlandığı bir senaryo gösterilmektedir. İstek başarılı olmazsa istemci hemen yeniden dener ve sonsuza kadar yeniden denemeye devam eder. Genellikle bu tür davranışlar bu örnektekinden daha hafiftir, 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.
}

Sorunu düzeltme

İstemci uygulamaları, yeniden deneme fırtınasına neden olmaması için bazı en iyi yöntemleri izlemelidir.

  • Yeniden deneme denemesi sayısını sınırlayıp uzun süre yeniden denemeye devam etmeyin. bir while(true) döngüsü yazmak kolay görünse de, isteğin başlatılmasına neden olan durum büyük olasılıkla değiştiğinden, uzun bir süre gerçekten yeniden denemek istemezsiniz. Çoğu uygulamada, birkaç saniye veya dakika boyunca yeniden denemek yeterlidir.
  • Yeniden deneme girişimleri arasında duraklatma. Bir hizmet kullanılamıyorsa, hemen yeniden denemenin başarılı olma olasılığı düşüktür. Örneğin üstel geri alma stratejisini kullanarak denemeler arasında bekleme süresini aşamalı olarak artırın.
  • Hataları zarif bir şekilde işleyin. Hizmet yanıt vermiyorsa, denemeyi durdurmanın ve bileşeninizin kullanıcısına veya çağırana bir hata döndürmenin mantıklı olup olmadığını göz önünde bulundurun. Uygulamanızı tasarlarken bu hata senaryolarını göz önünde bulundurun.
  • Yeniden deneme fırtınalarını önlemeye yardımcı olmak için özel olarak tasarlanmış Devre Kesici modelini kullanmayı göz önünde bulundurun.
  • Sunucu bir retry-after yanıt üst bilgisi sağlıyorsa, belirtilen süre geçene kadar yeniden denemeyi denemediğinizden emin olun.
  • Azure hizmetleriyle iletişim kurarken resmi SDK'ları kullanın. Bu SDK'lar genellikle yerleşik yeniden deneme ilkelerine ve yeniden deneme fırtınalarına neden olma veya bunlara katkıda bulunmaya karşı koruma sağlar. SDK'sı olmayan veya SDK'nın yeniden deneme mantığını doğru işlemediği bir hizmetle iletişim kuruyorsanız, yeniden deneme mantığınızı doğru şekilde işlemek ve kodu kendiniz yazmaktan kaçınmak için Polly (.NET için) veya (JavaScript için) gibi bir kitaplık kullanmayı göz önünde bulundurun.
  • 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 Daprgibi bu araçlar yeniden deneme ilkelerini destekler ve yinelenen denemelerden sonra geri dönme gibi en iyi yöntemleri otomatik olarak izler. Bu yaklaşım, yeniden deneme kodunu kendiniz yazmanız gerekmeyecek anlamına gelir.
  • İstekleri toplu olarak oluşturmayı ve varsa istek havuzunu kullanmayı göz önünde bulundurun. Birçok SDK, istek toplu işlemini ve bağlantı havuzunu sizin yerinize işler ve bu da uygulamanızın yaptığı toplam giden bağlantı denemesi sayısını azaltır, ancak yine de bu bağlantıları çok sık yeniden denememeye dikkat etmeniz gerekir.

Hizmetler ayrıca tekrar deneme dalgalarına karşı kendilerini korumalıdır.

  • Bir olay sırasında bağlantıları kapatabilmeniz için bir ağ geçidi katmanı ekleyin. Bu, Bulkhead deseni'nin bir örneğidir. Azure, Front Door, Application Gatewayve API Managementgibi farklı çözüm türleri için birçok farklı ağ geçidi hizmeti sağlar.
  • Ağ geçidinizdeki istekleri kısıtlar ve bu sayede arka uç bileşenlerinizin çalışmaya devam etmeyeceği kadar çok isteği kabul etmezsiniz.
  • Azaltma işlemi gerçekleştiriyorsanız, istemcilerin bağlantılarını ne zaman yeniden kurabileceklerini anlamalarına yardımcı olmak için bir retry-after üst bilgisi geri gönderin.

Hususlar

  • İstemciler döndürülen hata türünü dikkate almalıdır. Bazı hata türleri hizmetin başarısız olduğunu göstermez, bunun yerine istemcinin geçersiz bir istek gönderdiğini gösterir. Örneğin, bir istemci uygulaması 400 Bad Request hata yanıtı alırsa, sunucu isteğinizin geçerli olmadığını size anlattığından aynı isteği yeniden denemek büyük olasılıkla yardımcı olmayacaktır.
  • Müşterilerin bağlantıları yeniden denemek için makul olan süreyi göz önünde bulundurması gerekir. Yeniden denemeniz gereken süre, iş gereksinimlerinize ve bir hatayı bir kullanıcıya veya arayana makul bir şekilde iletip iletemeyeceğinize göre belirlenecek. Çoğu uygulamada, birkaç saniye veya dakika boyunca yeniden denemek yeterlidir.

Sorunu algılama

İstemci açısından bakıldığında, bu sorunun belirtileri çok uzun yanıt veya işlem sürelerinin yanı sıra bağlantıyı yeniden deneme girişimlerinin tekrarlandığını gösteren telemetriyi içerebilir.

Hizmet açısından bakıldığında, bu sorunun belirtileri kısa bir süre içinde bir istemciden çok sayıda istek veya kesintilerden kurtarılırken tek bir istemciden çok sayıda istek içerebilir. Belirtiler arasında, hizmet geri yüklenirken zorluk veya bir arıza onarıldıktan hemen sonra hizmetin sürekli kademeli arızaları da olabilir.

Örnek tanılama

Aşağıdaki bölümlerde, hem istemci tarafında hem de hizmet tarafında olası yeniden deneme fırtınasını algılamaya yönelik bir yaklaşım gösterilmektedir.

İstemci telemetri verilerinden 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ık olarak izlenir ve bir istemcinin aynı hizmete çok sayıda giden istekte bulunduğu zamanları belirlemek için bu bağlantılar hakkındaki bilgilere erişilebilir ve grafik oluşturulabilir.

Aşağıdaki grafik Application Insights portalındaki Ölçümler sekmesinden alınmıştır ve Bağımlılık hataları ölçümü Uzak bağımlılık adına göre bölünmüş olarak görüntülenmektedir. Bu, kısa bir süre içinde bir bağımlılıkla başarısız olan bağlantı girişimlerinin çok sayıda (21.000'den fazla) olduğu bir senaryoyu gösterir.

30 dakikalık bir süre içinde tek bir bağımlılıkta 21k bağımlılık hatalarını gösteren Application Insights'ın ekran görüntüsü

Sunucu telemetrisinden tanımlama

Sunucu uygulamaları tek bir istemciden çok sayıda bağlantı algılayabilir. Aşağıdaki örnekte, Azure Front Door bir uygulama için ağ geçidi işlevi görür ve tüm isteklerin bir Log Analytics çalışma alanına kaydedilmesi için yapılandırılmıştır.

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

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 fırtınası sırasında bu sorgunun yürütülmesi, tek bir IP adresinden çok sayıda bağlantı girişimi gösterir.

Bir saatlik süre içinde tek bir IP adresinden Front Door'a 81.608 gelen bağlantıyı gösteren Log Analytics'in ekran görüntüsü