Circuit Breaker Pattern Nedir? Dağıtık Sistemlerde Dayanıklılık
Evinizdeki sigorta kutusunu düşünün: Aşırı akım geldiğinde devre kesilir, tüm elektrik sisteminizin yanmasını önler. Circuit Breaker Pattern, yazılımda tam olarak aynı şeyi yapar.
Problem: Cascading Failures
Mikroservis mimarisinde servisler birbirine bağımlıdır. Servis A, Servis B'yi çağırır; Servis B, Servis C'yi çağırır. Eğer Servis C çökerse ne olur?
Kullanıcı → Servis A → Servis B → Servis C (ÇÖKMÜŞ!)
↓ ↓
bekliyor... bekliyor...
↓ ↓
timeout! timeout!
↓
TÜM SİSTEM ÇÖKER
Bu korkunç senaryoya cascading failure (zincirleme arıza) denir. Michael Nygard'ın "Release It!" kitabında detaylı olarak anlatılmıştır.
Çözüm: Circuit Breaker
Circuit Breaker, başarısız olan bir servise yapılan çağrıları otomatik olarak keser ve sistemin geri kalanını korur.
Üç Durum
- CLOSED (Kapalı) — Normal çalışma. İstekler servise iletilir.
- OPEN (Açık) — Devre kesilmiş. İstekler servise gitmez, anında hata döner.
- HALF-OPEN (Yarı Açık) — Test modu. Birkaç istek denenir, başarılı olursa CLOSED'a döner.
başarılı
CLOSED ────────→ CLOSED
│ ↑
│ hata eşiği │ test başarılı
│ aşıldı │
↓ │
OPEN ──(süre)──→ HALF-OPEN
↑ │
│ test başarısız│
└─────────────────┘
Nasıl Çalışır?
1. Hata Sayacı
Circuit Breaker, başarısız çağrıları sayar. Belirli bir eşik (ör. %50 hata oranı veya ardışık 5 hata) aşıldığında devre açılır.
2. Timeout Penceresi
Devre açıldıktan sonra belirli bir süre (ör. 30 saniye) tüm istekler engellenir. Bu süre, çöken servisin toparlanması için fırsat tanır.
3. Sağlık Kontrolü
Timeout süresi dolduktan sonra HALF-OPEN durumuna geçilir. Birkaç test isteği gönderilir. Başarılı olursa devre kapanır, başarısız olursa tekrar açılır.
Pratik Uygulama Örneği
class CircuitBreaker {
constructor(threshold = 5, timeout = 30000) {
this.failureCount = 0;
this.threshold = threshold;
this.timeout = timeout;
this.state = 'CLOSED';
this.lastFailure = null;
}
async call(serviceCall) {
if (this.state === 'OPEN') {
if (Date.now() - this.lastFailure > this.timeout) {
this.state = 'HALF_OPEN';
} else {
throw new Error('Circuit is OPEN');
}
}
try {
const result = await serviceCall();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
onSuccess() {
this.failureCount = 0;
this.state = 'CLOSED';
}
onFailure() {
this.failureCount++;
this.lastFailure = Date.now();
if (this.failureCount >= this.threshold) {
this.state = 'OPEN';
}
}
}
Fallback Stratejileri
Circuit Breaker açıkken ne yapılacağı da önemlidir:
- Varsayılan değer döndürme — Cache'ten eski veri sunma
- Alternatif servis — Yedek servise yönlendirme
- Graceful degradation — Özelliği geçici olarak devre dışı bırakma
- Kuyruğa alma — İsteği daha sonra işlenmek üzere kuyruğa ekleme
Gerçek Dünya Kullanımları
Netflix Hystrix
Netflix, Circuit Breaker'ın öncüsüdür. Hystrix kütüphanesi, her mikroservis çağrısını bir circuit breaker ile sarmalayarak sistemin %99.99 erişilebilirliğini sağlar.
BilgeOne Deneyimi
BilgeOne platformunda harici ödeme ve SMS servisleriyle entegrasyon yaparken Circuit Breaker kullandık. Ödeme servisi çöktüğünde tüm platform değil, sadece ödeme özelliği devre dışı kalıyor.
İlgili Desenler
| Desen | Amaç | |-------|------| | Circuit Breaker | Başarısız servise çağrı kesme | | Retry Pattern | Geçici hatalarda tekrar deneme | | Bulkhead Pattern | Kaynakları izole etme | | Timeout Pattern | Maksimum bekleme süresi |
Bu desenler birlikte dayanıklılık mühendisliği (resilience engineering) oluşturur.
Sonuç
Circuit Breaker, dağıtık sistemlerde hayat kurtaran bir desendir. Basit bir konsept olmasına rağmen, doğru implementasyonu sistemin güvenilirliğini dramatik şekilde artırır.
Bu konuyu ve diğer dayanıklılık desenlerini Yazılım Mimarisi 3.0 kitabında derinlemesine inceliyoruz. İnteraktif olarak pratik yapmak için LabLudus platformundaki DevOps kariyer yolunu takip edebilirsiniz.