Dayanıklılık Desenleri: Circuit Breaker, Bulkhead, Timeout
Yüksek trafikte dayanıklılık: circuit breaker durumları, bulkhead izolasyonu, timeout bütçeleri, retry fırtınalarından korunma ve kademeli çöküşün (cascading failure) anatomisi.
Kademeli çöküş (cascading failure) nasıl başlar?
Hep aynı senaryoyla: bir bağımlılık yavaşlar — çökmez, yavaşlar. Onu bekleyen thread'ler birikir, havuzlar dolar, bekleyenleri bekleyenler birikir ve beş dakika içinde sağlam servisler de cevap veremez olur. Dayanıklılık desenlerinin tamamı tek bir hedefe çalışır: bir bileşenin arızasını o bileşenin sınırında durdurmak. Bu yazı dört temel deseni ve birlikte çalışma düzenlerini kurar.
Desen haritası
Desen | Durdurduğu şey | Anahtar parametre |
|---|---|---|
Timeout | Sonsuz bekleme | Uçtan uca gecikme bütçesinin payı |
Retry (backoff+jitter) | Geçici hataların kullanıcıya yansıması | Deneme sayısı + retry bütçesi |
Circuit breaker | Ölü bağımlılığı dövmek | Hata eşiği, açık kalma süresi |
Bulkhead | Bir bağımlılığın tüm kaynakları tüketmesi | Bağımlılık başına havuz/izin sınırı |
Timeout: her çağrının vadesi vardır
Timeout'suz uzak çağrı, süresiz rehin verilmiş thread'dir. İki disiplin: birincisi, her dış çağrıda (HTTP, veritabanı, kuyruk, önbellek) açık timeout — kütüphane varsayılanlarına güvenilmez, çoğu 'sonsuz'dur. İkincisi, timeout'ların bütçe olarak tasarlanması: kullanıcıya 2 saniyede cevap sözü varsa, zincirdeki servislerin timeout'ları toplamda bu bütçeye sığmalıdır — A servisi 1,5sn bekleyip B'ye 1,5sn timeout verirse bütçe daha ilk halkada aşılmıştır. Bütçe, çağrı zinciri boyunca kalan süre olarak taşınır; kalan süre yetmeyecekse çağrı hiç yapılmaz, hızlı hata dönülür.
Retry: ilaç ve doz
Retry geçici hataları (ağ kesintisi, anlık yoğunluk) kullanıcıdan gizler; dozunda alınmazsa yükü katlayan zehirdir. Kurallar nettir: yalnızca idempotent ve geçici hata sınıflarında retry (bağlantı hatası evet, 400 asla, timeout ise 'işlem gerçekleşmiş olabilir' bilinciyle); exponential backoff + jitter (senkronize retry dalgalarını kırmak için); retry bütçesi (toplam trafiğin küçük bir yüzdesi — hata oranı yükselince retry'ın kendisi kısılır); ve zincirde tek katman retry yapar — her katman kendi başına denerse üç katmanlı zincirde bir hata 27 çağrıya patlar.
Circuit breaker: ölüyü dövmeyi bırakmak
Bağımlılık gerçekten hastaysa retry çare değil işkencedir. Devre kesici üç durumlu bir makinedir: Kapalı (normal akış; hata oranı izlenir) → eşik aşılınca Açık (çağrılar hiç yapılmaz, anında fallback döner; hasta sisteme nefes alanı) → süre dolunca Yarı-Açık (sınırlı deneme trafiği; başarılıysa Kapalı'ya, değilse Açık'a döner). İki mühendislik inceliği: eşikler istek hacmine duyarlı olmalı (10 istekte 5 hata ile 10.000 istekte 5.000 hata aynı oran, farklı anlam) ve breaker durumu panoda görünmelidir — 'hangi devreler açık?' sorusu, olay anında ilk bakılan ekrandır. Fallback tasarımı da breaker kadar önemlidir: önbellekten bayat veri, varsayılan cevap veya özelliğin zarifçe gizlenmesi — boş ekran fallback değildir.
Bulkhead: gemiyi bölmelere ayırmak
Adını gemi perdelerinden alan desen, kaynak izolasyonudur: her dış bağımlılığa ayrı havuz/eşzamanlılık sınırı tanınır — ödeme servisi çağrıları en fazla 50 eşzamanlı izin kullanır, öneri servisi 20. Öneri servisi yavaşladığında yalnızca kendi 20 iznini tüketir; ödeme yoluna dokunamaz. Sanal thread çağında havuzun yerini semaphore bazlı izin sınırları alır ama ilke değişmez: paylaşılan kaynak, paylaşılan kader demektir — izole edilmemiş her bağımlılık, en kritik akışınızın gizli ortağıdır. Kritik/kritik-olmayan ayrımı burada da geçerlidir: sipariş yolu ile raporlama aynı bağlantı havuzunu paylaşmamalıdır.
Desenlerin orkestrasyonu: sıralama ve sahiplik
Dört desen iç içe çalışır ve sıralaması önemlidir: dıştan içe bulkhead (izin var mı?) → circuit breaker (devre kapalı mı?) → timeout (bütçe yeter mi?) → çağrı → hata sınıfına göre retry kararı. Resilience4j gibi kütüphaneler bu zinciri bildirimsel kurar; kritik olan yapılandırmanın bağımlılık başına bilinçli yazılmasıdır — tüm servislere aynı kopyala-yapıştır değerler, dayanıklılık değil dekordur. Her bağımlılığın SLA'sı, hata karakteri ve iş kritikliği farklıdır; parametreler bu gerçeklikten türetilir ve chaos/yük testleriyle doğrulanır.
İş etkisi: arıza yerelken olay, yayılınca kriz olur
Dayanıklılık desenlerinin ticari karşılığı, arıza yarıçapının küçülmesidir: öneri servisi çöktüğünde öneriler kaybolur — satış devam eder; ödeme sağlayıcısı yavaşladığında ödeme kuyruğa alınır — site ayakta kalır. Bu fark, olay raporlarında 'kısmi hizmet etkisi' ile 'tam kesinti' arasındaki farktır ve SLA cezaları, kayıp ciro, itibar üçgeninde doğrudan paraya çevrilir. Desenler kurulduktan sonra tatbikatsız bırakılmamalıdır: bağımlılık arızası simülasyonları (chaos testleri), fallback'lerin gerçekten çalıştığının tek kanıtıdır.
Sık sorulan sorular
Circuit breaker her dış çağrıya mı kurulmalı?
Ağ üzerinden giden ve arızalanabilen her önemli bağımlılığa — evet. Maliyeti düşük, kazancı arıza anında büyüktür; ama parametreleri bağımlılığa özgü ayarlanmalıdır.
Timeout değerini nasıl seçerim?
Bağımlılığın gerçek gecikme dağılımından (p99 + pay) ve uçtan uca bütçeden geriye doğru. Sabit 30 saniye varsayılanı, pratikte 'timeout yok' demektir.
Retry ile idempotency ilişkisi ne?
Retry ancak tekrarı güvenli işlemlerde meşrudur. Yazma işlemlerinde idempotency anahtarı yoksa, timeout sonrası retry çift etki (çift sipariş, çift tahsilat) riskidir.
Bu desenler monolitte de gerekli mi?
Evet — monolit de veritabanına, ödeme sağlayıcısına, e-posta ve arama servislerine dış çağrı yapar. Kademeli çöküş mikroservis tekeli değildir.
Dayanıklılık kontrol listesi
Her dış çağrıda açık timeout; uçtan uca gecikme bütçesi tanımlı
Retry yalnızca idempotent+geçici sınıfta; backoff+jitter+bütçe kurulu
Zincirde retry tek katmanda; katmanlar arası çarpan yok
Kritik bağımlılıklarda circuit breaker + anlamlı fallback
Bağımlılık başına bulkhead/izin sınırı; kritik yollar izole
Breaker durumları ve bağımlılık sağlığı panoda
Chaos/arıza tatbikatları düzenli; fallback'ler kanıtlı
SSH Yazılım, dayanıklılık desenlerinin tasarımını ve Resilience4j tabanlı kurulumunu uçtan uca gerçekleştirir. Arıza yarıçapınızı birlikte küçültelim.