System Design

Mikroservisler İçin Adaptif Yükleme Dengeleme

Statik yükleme dengeleme stratejileri, örneklerin talebe göre ölçeklendiği dinamik mikroservis ortamlarında genellikle başarısız olur. Geleneksel sırayla (round-robin) veya en az bağlantı yöntemleri, sunucu performansının homojen olduğunu varsayar; bu da üretimde nadiren doğrudur. Adaptif yükleme dengeleme, servis sağlığını sürekli izleyerek ve trafik ağırlıklarını gerçek zamanlı olarak ayarlayarak bu sorunu çözer; bu da optimum kaynak kullanımını sağlar ve gecikmeyi en aza indirir.

Statik Ağırlıklandırmanın Sorunu

Tipik bir mikroservis mimarisinde, bir ödeme servisinin beş örneği olabilir. Başlangıçta tüm örnekler sağlıklıdır. Ancak, bir örnekte çöp toplama (garbage collection) duraksamaları, yüksek CPU kullanımı veya bellek sızıntıları başlayabilir. Statik bir yük dengeleyici, trafiği tüm beş örneğe göndermeye devam eder; bu da zorlanan düğümle karşılaşan kullanıcılar için gecikmeyi artırır. Sonunda, o düğüm tamamen başarısız olabilir ve yük dengeleyici yeterince hızlı tepki vermezse zincirleme bir arızaya neden olabilir.

Gerçek Zamanlı Sağlık Kontrolleri

Etkili adaptif dengeleme, ayrıntılı sağlık kontrolleriyle başlar. Yalnızca HTTP durum kodlarına güvenmek yerine, yanıt sürelerini, hata oranlarını ve doygunluk metriklerini izleriz. Her servis örneği için üç durum tanımlarız: Sağlıklı, Degraded (Zayıflamış) ve Sağlıksız. Bir örneğin yanıt süresi bir eşiği aşarsa (örneğin, 95'inci yüzdelik gecikme taban çizgisinin 2 katıysa) veya hata oranı belirli bir yüzdeliği aşarsa Degraded olarak kabul edilir.

Dinamik Ağırlıklandırma Algoritması

Sağlık verilerine sahip olduğumuzda, her örnek için dinamik bir ağırlık hesaplarız. Ağırlık, bir örneğin bir sonraki isteği alma olasılığını belirler. Burada basit bir üstel azalma modeli iyi çalışır. Zamanla azalan, her örnek için bir "performans puanı" tutarız. Başarılı istekler puanı artırırken, yavaş veya başarısız istekler puanı azaltır. Ağırlık, bu puanlara göre normalize edilir.


function calculateDynamicWeight(instance, healthData) {
    const baselineLatency = 100; // ms
    const currentLatency = healthData.latency;
    const errorRate = healthData.errorRate;
    
    // Yüksek gecikme için ceza
    const latencyPenalty = Math.max(0, (currentLatency - baselineLatency) / baselineLatency);
    
    // Hatalar için ceza
    const errorPenalty = errorRate * 10;
    
    // Birleşik puan: Düşük olan daha iyi
    const totalPenalty = latencyPenalty + errorPenalty;
    
    // Ağırlıklar, cezaya ters orantılıdır
    // Minimum ağırlık, kurtarma testleri için bazı trafiğin hala akmasını sağlar
    return Math.max(0.1, 1.0 - totalPenalty);
}

Uygulama Stratejisi

Uygulamada, bu mantık genellikle bir servis ağı yan tarafına (sidecar) (Envoy veya Linkerd gibi) veya merkezi bir yük dengeleyiciye gömülüdür. Sidecar tabanlı adaptif dengeleme, sağlık kontrolleri yerel olduğu için daha düşük gecikme sunar. Sidecar, her üst akış (upstream) örneğinin performansını izler ve yönlendirme kararlarını milisaniyeler içinde ayarlar. Örneğin, Örnek A'nın gecikmesi artarsa, istemci servisindeki sidecar, merkezi bir orkestratörün tepki vermesini beklemeden trafiği hemen Örnek B ve C'ye yönlendirir.

Flapping ve Histeresizin Yönetimi

Yaygın bir tuzak, geçici sorunlar nedeniyle bir örneğin Sağlıklı ve Sağlıksız durumları arasında hızla geçiş yapması olan "flapping"tir. Bunu önlemek için histeresiz (gecikmeli tepki) getiririz. Bir örneğin ağırlığının tamamen geri yüklenmeden önce belirli bir süre (örneğin, 30 saniye) sağlıklı olması gerekir. Benzer şekilde, Sağlıksız olarak işaretlenmeden önce kısa bir süre boyunca (örneğin, 5 saniye) tutarlı bir şekilde başarısız olması gerekir. Bu yumuşatma, yük dengeleyicinin trafiği gereksiz yere salınım yapmasını önler.


class InstanceTracker {
    constructor(instanceId) {
        this.instanceId = instanceId;
        this.state = 'HEALTHY';
        this.lastStateChange = Date.now();
        this.consecutiveFailures = 0;
        this.consecutiveSuccesses = 0;
    }

    recordResult(success, latencyMs) {
        if (success) {
            this.consecutiveSuccesses++;
            this.consecutiveFailures = 0;
            
            // Histeresiz: DEGRADED durumundan kurtulmak için 30 sn başarı gerektirir
            if (this.state === 'DEGRADED' && Date.now() - this.lastStateChange > 30000) {
                this.state = 'HEALTHY';
                this.lastStateChange = Date.now();
            }
        } else {
            this.consecutiveFailures++;
            this.consecutiveSuccesses = 0;
            
            // Histeresiz: UNHEALTHY olarak işaretlemek için 5 hata gerektirir
            if (this.consecutiveFailures >= 5) {
                this.state = 'UNHEALTHY';
                this.lastStateChange = Date.now();
            } else if (this.consecutiveFailures >= 2) {
                this.state = 'DEGRADED';
                this.lastStateChange = Date.now();
            }
        }
    }
}

Sonuç

Adaptif yükleme dengeleme, dayanıklı mikroservis mimarileri oluşturmak için vazgeçilmezdir. Statik yapılandırmaların ötesine geçerek gerçek zamanlı, performans odaklı yönlendirmeye geçmek, kullanıcı deneyimini ve sistem güvenilirliğini önemli ölçüde iyileştirebilir. Temel sağlık kontrolleri ve gecikmeye dayalı ağırlıklandırma uygulayarak başlayın, ardından eşiklerinizi ve histeresiz parametrelerinizi belirli servis özelliklerinize göre iyileştirin. Unutmayın, amaç sadece arızadan kaçınmak değil, baskı altında zarifçe (gracefully) performans düşüşü yaşamaktır.

Share: