Üçüncü parti API bağımlılığında Circuit Breaker'ı nasıl kurarım?
Soru
Uygulamamız kargo fiyatını harici bir kargo API'ından çekiyor. Kargo firması yavaşlayınca ya da çökünce isteklerimiz timeout'a düşüyor, Octane/PHP-FPM worker'ları bloke oluyor ve tüm sistem kilitleniyor. Bu zincirleme çökmeyi önlemek için Circuit Breaker'ı Guzzle middleware veya Go kütüphanesiyle nasıl kurarım? Devre Açık/Kapalı/Yarı-Açık durumlarında sistem nasıl davranmalı?
Cevap
Kısa cevap: Circuit breaker tek başına sizi kurtarmaz — onu agresif bir timeout ile birlikte kurarsanız kurtarır. Çünkü worker’larınızı öldüren şey hatanın kendisi değil, o hataya kadar geçen 30 saniyelik bekleme.
Kısa cevap
Yaşadığınız şey klasik zincirleme çökme (cascading failure): yavaş bir bağımlılık, her isteği timeout’a kadar bekletir, havuz dolar, sistem kilitlenir. Breaker’ın işi, çöken bir bağımlılığı çağırmayı tamamen kesmek. Worker’ın istekler arasında ayakta kaldığı bir mimaride bunun neden daha sert vurduğunu Laravel Octane yazısında anlatmıştım.
Neden
-
Sizi öldüren hata değil, bekleme. Bağımlılık hızlı hata dönseydi worker anında serbest kalırdı; 30 saniyelik timeout havuzu doldurur.
-
Breaker’ın üç durumu bir protokoldür.
CLOSED: çağrılar geçer, hatalar sayılır. Eşik aşılıncaOPEN: bağımlılığı hiç çağırma, anında fallback dön, bir süre (cooldown) böyle kal. Cooldown bitinceHALF-OPEN: birkaç deneme isteğini içeri al — başarılıysaCLOSED’a dön, yine hata varsa tekrarOPEN’a geç. -
Tek bir bağımlılık tüm havuzu tüketmemeli. İzolasyon olmadan kargo API’nin yavaşlığı sepet ve ödemeyi de aşağı çeker.
Ne yapmalı
-
Önce timeout’u kısın, asıl katil o.
connect_timeoutvetimeout’u saniyeler değil milisaniyeler seviyesinde tutun (örn. 800ms-2s). Kısa timeout olmadan breaker işe yaramaz. -
Breaker’ı üç durumuyla kurun. Yukarıdaki
CLOSED/OPEN/HALF-OPENdöngüsü; eşik ve cooldown değerlerini gerçek hata oranınıza göre seçin. -
Bulkhead ile o bağımlılığı izole edin. Kargo API’ye aynı anda gidebilecek istek sayısını sınırlayın; o servis yavaşladığında sadece ona ayrılmış küçük bir dilim tükensin.
-
Fallback’i önceden tanımlayın. Son cache’lenmiş kargo fiyatını dönün, olmuyorsa “tahmini ücret şu an hesaplanamıyor” deyin. Hata sayfası yerine bozulmuş ama çalışan bir deneyim sunun.
-
Aracı doğru seçin. Laravel’de Guzzle client’ını bir middleware’e sarın, durumu Redis’te tutun. Go’da elle yazmayın —
sony/gobreakerzaten bu üç durumu veriyor.
Sonuç: Ben olsam breaker’ı asla yalnız bırakmam: kısa timeout + bulkhead + cache’li fallback üçlüsüyle kurarım. Worker’ların timeout beklerken bloke olması özellikle kalıcı süreçli mimaride (Octane) çok daha sert vurur; o yüzden önce timeout’u kısın, sonra breaker’ı ekleyin.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.