Devre kesici (circuit breaker) uygulaması: mikroservislerde kaskad hatayı önlemek
Circuit breaker (devre kesici) deseninin durumları, Resilience4j ile uygulama, eşik ayarları, yedek davranış ve izleme adımlarını öğrenin.
Circuit breaker deseni neyi çözer?
Mikroservislerde bir servis başka bir servisi ağ üzerinden çağırır. Çağrılan servis yavaşlarsa ya da yanıt vermezse, çağıran servis zaman aşımı dolana kadar iş parçacıklarını, bağlantıları ve belleği bekleyen isteklerle tüketir. Kaynaklar tükenince çağıran servis de yanıt veremez hale gelir; sorun zincirleme olarak yukarı yayılır. Buna kaskad hata denir.
Circuit breaker (devre kesici), korunan çağrıyı bir sarmalayıcıyla çevreler ve hata arttığında çağrıyı hiç denemeden hemen hata döndürür. Elektrik devresindeki sigorta mantığına benzer: aşırı yük olduğunda devre açılır, hasar yayılmaz, sorun giderilince devre kapanır. Böylece çağıran servis kaynaklarını korur, çağrılan servise de toparlanması için nefes alacak alan bırakır.
Desen tek başına yeterli değildir; zaman aşımı, yeniden deneme ve bölme (bulkhead) gibi dayanıklılık desenleriyle birlikte düşünülür. Örneğin her çağrıda uygun bir zaman aşımı yoksa devre kesici hatayı fark etmekte gecikir; kontrolsüz yeniden denemeler ise zaten zorlanan servisi daha da yorar.
Durumlar ve çalışma mantığı
Devre kesici kavramsal olarak şu durumlarda çalışır:
- Kapalı (closed): Çağrılar normal akar, başarı ve hata sonuçları kaydedilir. Hata ölçütü eşiği aşmazsa kapalı kalır.
- Açık (open): Eşik aşıldığında devre açılır. Çağrılar uzak servise gitmeden anında reddedilir. Belirli bir bekleme süresi dolana kadar bu durum sürer.
- Yarı açık (half-open): Bekleme süresi bitince sınırlı sayıda deneme çağrısına izin verilir. Bunlar başarılıysa devre kapanır; başarısızsa tekrar açılır ve bekleme yeniden başlar.
Martin Fowler'ın anlatımında temel parametreler çağrı zaman aşımı, devreyi açan hata eşiği ve yeniden deneme öncesi bekleme süresidir. Basit bir uygulama hata sayısını sayarken, gelişmiş uygulamalar hata oranına ya da yavaş çağrı oranına göre karar verir. Önemli bir ayrıntı: her hata devreyi açmamalıdır. İş kuralından doğan, normal akışa ait hatalar (örneğin yanlış parola) uzak servisin sağlığını yansıtmaz ve sayılmamalıdır.
Resilience4j ile uygulama
Java dünyasında yaygın kütüphane Resilience4j'dir. Bu kütüphanede devre kesici, belirli bir kayan pencerede (sliding window) çağrı sonuçlarını toplar. Pencere ya son çağrıların sayısına (COUNT_BASED) ya da son saniyelere (TIME_BASED) göre kurulabilir. Başlıca ayarlar:
- failureRateThreshold: hata oranı bu eşiği aştığında devre açılır.
- slowCallDurationThreshold ve slowCallRateThreshold: belirli süreyi aşan çağrılar yavaş sayılır; yavaş çağrı oranı eşiği aşarsa devre açılır.
- slidingWindowType ve slidingWindowSize: pencere tipi ve boyutu.
- minimumNumberOfCalls: oranın hesaplanması için gereken asgari çağrı sayısı. Az çağrıyla oran yanıltıcı olacağından bu değer önemlidir.
- waitDurationInOpenState: devrenin açık kalacağı süre.
- permittedNumberOfCallsInHalfOpenState: yarı açık durumda izin verilen deneme sayısı.
- recordExceptions ve ignoreExceptions: hangi istisnaların hata sayılacağı.
Örnek yapı şöyledir:
CircuitBreakerConfig config = CircuitBreakerConfig.custom() .failureRateThreshold(hataEsigi) .slidingWindowType(SlidingWindowType.COUNT_BASED) .slidingWindowSize(pencereBoyutu) .minimumNumberOfCalls(asgariCagri) .waitDurationInOpenState(Duration.ofSeconds(beklemeSaniye)) .permittedNumberOfCallsInHalfOpenState(denemeSayisi) .build();
CircuitBreaker breaker = CircuitBreaker.of("odemeServisi", config); Supplier<String> korunanCagri = CircuitBreaker.decorateSupplier(breaker, () -> odemeServisiniCagir());
Devre açıkken kütüphane CallNotPermittedException fırlatır. Bu istisnayı yakalayıp yedek davranışa (fallback) yönlendirmek tasarımın parçasıdır. Değerleri kendi trafiğinize göre seçin: kütüphane varsayılanları genel amaçlıdır ve her servis için uygun olmayabilir.
Yedek davranış: devre açıkken ne yapılır?
Devre kesicinin değeri, açıkken istemcinin ne yaptığıyla ölçülür. Yalnızca hata fırlatmak bazı durumlarda doğrudur, ama çoğu zaman daha iyi seçenekler vardır:
- Önbellekten eski ama kullanılabilir veri göstermek (ürün listesi, kur bilgisi).
- Varsayılan değer döndürmek (öneri servisi çalışmıyorsa genel öneri listesi).
- İşi kuyruğa alıp sonra yeniden işlemek (ödeme onayını sonradan tamamlamak).
- İşlevi kapatıp kullanıcıya açık bir mesaj göstermek.
Hangi yedek davranışı seçeceğinize iş sahibiyle birlikte karar verin. Örneğin bir e-ticaret sayfasında yorum servisi çökmüşse ürün sayfası yorumlar olmadan açılmalıdır; ödeme servisi çökmüşse sipariş sessizce tamamlanmış gibi gösterilmemelidir. Yedek davranış da test edilmeli; çünkü nadiren çalıştığı için bozuk kalma riski yüksektir.
Yedek davranışların kendisi başka bir uzak servise bağlıysa, o da devre kesici ile korunmalıdır; aksi hâlde yedek yol da aynı kaskadı üretir.
Gözlemlenebilirlik ve işletme
Devre kesici sessizce çalışırsa sorunları gizler. Fowler, devre durum değişikliklerinin kaydedilmesini ve açıldığında operatörlere uyarı gitmesini önerir. Uygulamada şunları izleyin: devre durumu (kapalı, açık, yarı açık), hata ve yavaş çağrı oranı, reddedilen çağrı sayısı, durum geçiş olayları. Resilience4j bu olayları ve ölçümleri dışarı verecek yapıya sahiptir ve yaygın ölçüm araçlarına bağlanabilir.
Panolarda devre durumunu servis bağımlılık haritasıyla birlikte gösterin: hangi servis hangi bağımlılığı koruyor? Bir devre sık sık açılıp kapanıyorsa (titreşim) eşikler fazla hassas, bekleme süresi fazla kısa ya da bağımlı servis gerçekten kararsız olabilir. Operasyon ekibinin devreyi elle açabilmesi ya da kapatabilmesi, olay anında işe yarar.
Dağıtımlarda bir de ortam farkı vardır: devre kesici durumu genellikle her uygulama örneğinde ayrı tutulur. Bir örnek bağımlılığı bozuk görürken öbürü sağlıklı görebilir. Bunu tasarımda hesaba katın ve eşikleri tek bir örneğe gelen trafik miktarına göre ayarlayın.
Sık yapılan hatalar
En sık hata, zaman aşımı koymadan devre kesici kurmaktır: yanıt gelmeyen çağrı hata olarak sayılmazsa devre hiç açılmaz. İkinci hata, iş kuralı hatalarını hata sayıp devreyi gereksiz yere açmaktır. Üçüncü hata, asgari çağrı sayısını çok düşük tutmak: çok az trafikte tek bir hata devreyi açabilir.
Diğer hatalar: tek bir devre kesiciyi birbirinden farklı uç noktalar için paylaşmak (yavaş bir uç nokta diğerlerini de keser), yedek davranışı hiç test etmemek, yeniden deneme ile devre kesicinin sırasını yanlış kurmak, devre kesici durumunu izlememek, yanlış varsayılanlarla üretime çıkmak.
Devre kesici, altta yatan sorunu çözmez; yalnızca sorunun yayılmasını sınırlar. Devre sık açılıyorsa asıl nedeni (kapasite, yavaş sorgu, ağ) bulup düzeltmek gerekir. Yük testleri ve kaos denemeleriyle bağımlılığı bilerek yavaşlatıp devrenin beklediğiniz gibi davrandığını doğrulayın.
Bu beceriyi geliştirmek için eğitim bağlamı
Devre kesici, mikroservis dayanıklılığının bir bileşenidir; servis iletişimi, zaman aşımı ve gözlemlenebilirlik ile birlikte öğrenilir.
Mindset'in Mikroservis Mimarisi eğitiminde servisler arası iletişim, dayanıklılık desenleri ile gözlemlenebilirlik ve işletme modülleri yer alır. Java Mikroservisleri (Spring Cloud) eğitiminde servisler arası iletişim ve dayanıklılık modülü ayrıca bulunur. Bu içerikler Java ve arka uç geliştiricileri, mimarlar ve platform mühendisleri için uygundur; ekiplerde ortak bir dayanıklılık standardı kurmak için kullanılabilir.
İlgili Mindset programı
Mikroservis Mimarisi
Sık sorulan sorular
Circuit breaker ile retry (yeniden deneme) aynı şey midir?
Hayır. Yeniden deneme, başarısız çağrıyı tekrar dener; devre kesici ise hata arttığında çağrıları hiç denemeden reddeder. Kontrolsüz yeniden denemeler zaten zorlanan servisi daha da yorar. İkisi birlikte kullanılacaksa sınırlı deneme sayısı ve gecikme (backoff) gerekir, devre kesici bunların dışındaki koruma katmanıdır.
Devre açıldığında kullanıcı ne görmeli?
Bu iş kararıdır. Seçenekler: önbellekteki eski veriyi göstermek, varsayılan içerik sunmak, işi kuyruğa alıp sonra tamamlamak ya da açık bir hata mesajı vermek. Kritik işlemlerde (ödeme) sessizce başarılı gibi davranmak yanlıştır. Her kritik çağrı için yedek davranışı önceden belirleyin ve test edin.
Resilience4j mi başka bir çözüm mü?
Resilience4j Java ekosisteminde yaygın ve resmî belgesi geniş bir kütüphanedir. Başka dillerde de benzer kütüphaneler vardır. Hizmet ağı (service mesh) kullanan ortamlarda devre kesici davranışı proxy düzeyinde de tanımlanabilir. Seçimde ekibin dili, işletme modeli ve gözlemlenebilirlik altyapısı belirleyicidir.
Hangi hatalar devreyi açmalı?
Uzak servisin sağlığını yansıtan hatalar: zaman aşımı, bağlantı hataları, sunucu hataları. İş kuralından doğan hatalar (geçersiz giriş, yetkisizlik) sayılmamalıdır. Resilience4j'de bu ayrım recordExceptions ve ignoreExceptions ayarlarıyla yapılır. Yanlış ayrım, devrenin gereksiz açılmasına ya da hiç açılmamasına yol açar.
Devre kesici durumunu nasıl test ederim?
Bağımlı servisi test ortamında bilerek yavaşlatın ya da hata verdirin; devrenin açıldığını, yedek davranışın çalıştığını ve bekleme süresi sonrası yarı açık durumdan kapanışa geçildiğini gözlemleyin. Birim testlerde yapay hata üreten sahte servisler kullanılabilir. Üretimde durum ölçümlerini izlemek de doğrulamanın parçasıdır.
İlgili rehberler
İlgili eğitimler
Kategori: Yazılım Geliştirme