Nedir bu Circuit Breaker Pattern ? 🔌
Circuit breaker Türkçe anlamıyla sigorta salter,
alternatif ve doğru akım devrelerinde kullanılan cihazları ve bu cihazlara mahsus iletkenleri, aşırı akımlardan koruyarak devreleri ve cihazı hasardan kurtaran açma elemanlarına denir. Yani kısaca sistemde aşırı yüklenmenin olduğu durumların üstesinden gelmek için kullanılan bir devre elemanıdır.
Yazılım dünyasında circuit breaker nasıl kullanılır ? 💻
Sistemimize Microservice mimarisini uyguladık ve ardışık olarak birbirini request gönderen bir dizi servisimiz mevcut. Diğer bütün servisler gibi bu dizideki servislerin de down olma ihtimali var ve eğer herhangi biri requestlere cevap veremezse bu bütün akışı aksatıp bir dizi ardışık hataya sebep olabilir. Eğer bu cevap dönemeyen requesti yapan çok fazla caller olursa bu da kaynak tüketimi kritik düzeyde arttırıp bir çok servisi ve butun sistemi etkileyecek bir dizi ciddi soruna yol acabilir.
Circuit breaker bu gibi durumlarda bir devre anahtarı gibi davranarak belli bir thresholdun(eşik değeri) üstünde hata alındığında, response dönemeyen servise gelen requestleri servise iletmeden(open_state), requestlere bir hata mesajı veya bilgi verici mesajla dönüş yaparak sistemin gereksiz yere aşırı yüklenmesini engeller. Belli bir timeouttan sonra gelen requestlerin bir kısmını servise ileterek test yapıp sistem durumunu kontrol eder(half_open state).Eğer sıkıntı giderilmiş ise bütün isteklerin geçmesine izin verir (closed state) ve sistem düzeni korunmuş olur, eğer test çağrıları da hata mesajı alıyorsa, yine requestlere error donup bu döngüyü devam ettirir.
Bahsetmiş olduğumuz bu patternin popüler dillerde implementasyonları mevcuttur.
Nodejs → https://github.com/nodeshift/opossum
Golang → https://github.com/sony/gobreaker
Netflix OSS → https://github.com/Netflix/Hystrix
Java → https://github.com/resilience4j/resilience4j
Peki bu circuit breaker nasıl çalışır?
Circuit breaker, başarısız olabilecek requestler icin bir proxy gibi davranır yani gelen requestleri ve responselari dinleyip gerektiği durumda müdahale edebilecek sekilde tasarlanmıştır. Bu proxy, kaç tane requestin basarisiz oldugunu izleyip verilen parametrelere gores aksiyon alır. Eğer belirlenen bir eşik değerinden daha fazla istek fail durumuna düşmüş ise gelen istekleri servise yönlendirmeden, callera bir hata-bilgilendirme mesaj dönerek daha fazla requestin cevap bekleyerek sistemi yormasını önler.
Bu proxynin nasıl çalıştığının state machine gösterimi aşağıdaki gibidir;
Closed: Anahtar kapalı durumdayken servise gelen isteklere belirli bir hata oranına kadar basarili bir sekilde response dönülebilmektedir. Proxy, basarisiz ve cevapsız requestler icin bir counter tutar ve bu counterin degeri, belirli bir zaman aralığında belirli bir thresholdu geçerse proxy açık duruma geçer ve yine parametre olarak verilen timeout suresinden sonra kendisini half-open konumuna alır.
Open: Anahtar açıkken gelen butun requestler servise gönderilmeden fail edilir ve response olarak bir exception veya bilgi içeren bir mesaj dondurulur.
Half-Open: Uygulamaya gelen requestlerin bir kısmı servise gönderilip response beklenir. Eğer response hepsi başarılı bir şekilde dönerse, daha önce hataya sebep olan hatanın giderildiği varsayılır ve anahtar tamamen kapatılır, counter sıfırlanır ve butun requestlerin gecişine izin verilir. Eğer gönderilen limitli requestlerden herhangi biri fail olursa problemin hala devam ettigi varsayılır ve anahtar tekrar açık duruma gelir. Timeout sıfırdan başlar hata giderilene veya müdahale edilene kadar bu döngü devam eder.
Peki ne zaman işimize yarayabilir ? ⛑
Örneğin Trendyolda biz mobil clientların içerideki internal api lere olan entegrasyonlarını daha güvenilir hale getirmek , istenilen response modeline uygun datayı aggregate(toplayıp) edip ,basitleştirip oluşturmak , request ve response headerlar üzerinde filtreleme yapmak vb. gibi işler için bir BFF katmanı (https://samnewman.io/patterns/architectural/bff/) uygulamaktayız .
Bu BFF katmanımızdaki projemizin kendisini her zaman downstream api/remote service lerde gerçekleşebilecek bir hataya karşı korumalı ve mümkün olduğunca clientları bu hatayla karşı karşıya getirmemelidir bu gibi projelerde olmazsa olmaz kullanılması gereken bir patterndir. Biz BFF katmanında bulunan bu projemizi Spring Boot teknolojisi ile geliştirdik ve Circuit Breaker Pattern’i ise Spring’in Netflix OSS ‘tan alıp implemente ettiği Spring Cloud Netflix projesinin Hystrix kütüphanesi ile gerçekleştirdik.Aşağıda linkini paylaştığım adresler bu kütüphanenin Spring Boot’a nasıl entegre edilebileceğini göstermekte.
https://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html#_circuit_breaker_hystrix_clients
https://github.com/Netflix/Hystrix/wiki/Configuration
https://www.baeldung.com/spring-cloud-netflix-hystrix