Sebuah service call dapat gagal dengan cepat tetapi tetap menimbulkan masalah yang lebih besar pada sistem. Ketika setiap request upstream terus memanggil dependency downstream yang sedang gagal, setiap percobaan menghabiskan kapasitas koneksi, waktu worker, retry budget, dan ruang queue. Dependency menerima traffic yang belum mampu dilayaninya, sementara caller menghabiskan resource untuk menunggu hasil yang sangat berkorelasi dengan kegagalan sebelumnya.
Circuit breaker menempatkan batas keputusan yang memiliki state di depan call tersebut. Alih-alih memperlakukan setiap request sebagai kesempatan terpisah untuk mencoba dependency, breaker mencatat state kegagalan terbaru dan dapat menolak call secara lokal selama interval terbatas. Pemulihan kemudian diuji melalui probe terkontrol, bukan dengan langsung mengembalikan seluruh traffic.
Mekanisme ini tidak membuat dependency yang gagal menjadi sehat. Circuit breaker mengubah cara kegagalan merambat melalui caller.
State closed mempertahankan jalur call normal
Breaker biasanya dimulai pada state closed. Call diteruskan ke dependency, dan hasilnya berkontribusi pada kebijakan kegagalan yang digunakan implementasi. Kebijakan tersebut dapat menghitung kegagalan berturut-turut, menghitung rasio kegagalan pada sampel terbatas, atau mengklasifikasikan hasil tertentu sebagai kegagalan yang relevan bagi breaker.
Klasifikasi ini penting. HTTP 500, penolakan koneksi, dan timeout lokal dapat menandakan kegagalan dependency. HTTP 400 akibat input caller yang tidak valid biasanya menyatakan kondisi berbeda. Menganggap setiap hasil non-sukses sebagai bukti kesehatan dependency dapat membuka breaker meskipun dependency memproses traffic dengan benar.
Karena itu, breaker memerlukan model hasil yang eksplisit. Breaker juga memerlukan model sampling. Ambang lima kegagalan memiliki arti berbeda ketika ada lima call per jam dibanding lima ribu call per detik. Kebijakan berbasis rasio memerlukan ukuran sampel minimum agar noise pada volume rendah tidak memicu perubahan state secara mendadak.
Selama breaker tetap closed, mekanisme ini menambahkan observasi dan kebijakan tanpa sengaja menahan call normal.
State open mengubah kegagalan remote menjadi keputusan lokal
Setelah kondisi trip yang dikonfigurasi terpenuhi, breaker berpindah ke open. Call yang mencapai breaker ditolak tanpa memanggil dependency yang dilindungi.
Perubahan ini mengubah jalur resource. Call yang ditolak secara lokal tidak memerlukan koneksi downstream, tidak menempati slot request downstream, dan tidak menunggu timeout remote. Jika caller memiliki fallback, nilai stale, jalur deferred work, atau respons unavailable yang eksplisit, perilaku tersebut dapat dimulai segera.
Penolakan lokal bukan keberhasilan. Aplikasi tetap harus merepresentasikan operasi yang tidak tersedia secara benar. Mengembalikan sukses palsu hanya menyembunyikan kegagalan dependency dan dapat melanggar invariant aplikasi.
Interval open juga perlu dibedakan dari rate limiter. Rate limiter membatasi admission request berdasarkan kebijakan traffic. Breaker menahan call karena hasil yang diamati menunjukkan bahwa operasi yang dilindungi sedang tidak sehat atau tidak cocok menerima percobaan lanjutan. Keduanya dapat menolak pekerjaan, tetapi transisi state dan bukti yang mendasarinya berbeda.
State half-open mengontrol batas pemulihan
Breaker yang open tidak dapat tetap open selamanya jika dependency dapat pulih. Setelah interval yang dikonfigurasi, banyak desain masuk ke state half-open dan mengizinkan sejumlah kecil probe call.
Batas jumlah probe merupakan bagian utama desain. Jika semua request yang menunggu dilepas sekaligus, breaker dapat menciptakan kembali tekanan yang ada sebelum state open. State half-open sebaliknya menerima sampel pemulihan kecil sementara call lain tetap mendapat penolakan lokal.
Probe yang sukses dapat menggerakkan breaker menuju closed. Probe yang gagal dapat mengembalikannya ke open dan memulai ulang interval tunggu. Implementasi berbeda dalam menentukan apakah satu keberhasilan cukup, beberapa keberhasilan diperlukan, atau sampel terbatas dievaluasi. Pilihan tersebut merupakan kebijakan, bukan semantik universal circuit breaker.
Concurrency membuat transisi ini konkret. Jika beberapa thread melihat interval open telah berakhir, semuanya tidak boleh secara independen memutuskan bahwa mereka memiliki satu-satunya probe yang diizinkan. State breaker dan probe budget memerlukan sinkronisasi atau transisi state atomik yang sesuai dengan runtime.
Scope breaker menentukan kegagalan yang dianggap berkorelasi
Breaker berguna hanya jika state-nya mengelompokkan call yang benar-benar berbagi failure domain. Satu breaker global untuk seluruh outbound request dapat mengikat dependency yang tidak berkaitan: kegagalan satu service dapat menahan call menuju service lain yang sehat.
Pada ekstrem sebaliknya, breaker per request key dapat memecah observasi sedemikian jauh sehingga tidak ada breaker yang mengumpulkan cukup bukti untuk trip. Pendekatan itu juga dapat menciptakan state tanpa batas jika variasi key sangat tinggi.
Scope yang umum mencakup remote service, endpoint service, pasangan host dan port, atau operasi tertentu yang perilaku kegagalannya berbeda secara material dari operasi lain. Batas yang tepat mengikuti topologi dependency dan resource.
Connection pool menambahkan dimensi lain. Beberapa operasi logis dapat berbagi satu pool sehingga juga berbagi perilaku saturasi, meskipun semantik aplikasinya berbeda. Breaker yang hanya di-scope berdasarkan nama method dapat melewatkan batas resource bersama tersebut.
Timeout dan retry tetap menjadi kontrol terpisah
Circuit breaker tidak menggantikan timeout. Ketika breaker closed dan sebuah call diterima, caller tetap memerlukan batas durasi percobaan tersebut dalam memakai resource.
Circuit breaker juga tidak membuat retry bebas risiko. Kebijakan retry dapat melipatgandakan percobaan sebelum breaker memiliki cukup bukti untuk open. Jika beberapa layer service melakukan retry secara independen, satu request pengguna dapat berkembang menjadi banyak percobaan downstream. Breaker pada akhirnya dapat menghentikan traffic itu, tetapi tidak dapat membatalkan pekerjaan yang sudah dibuat oleh retry loop bertingkat.
Kontrol-kontrol ini memerlukan budget yang kompatibel. Request deadline membatasi total waktu yang masih berguna. Per-attempt timeout membatasi call individual. Kebijakan retry menentukan apakah percobaan lain layak dilakukan. Breaker menentukan apakah state dependency saat ini mengizinkan percobaan sama sekali.
Menempatkan keputusan tersebut dalam urutan yang disengaja membuat perilaku lebih mudah dianalisis. Retry yang bertemu breaker open biasanya perlu menerima hasil breaker lokal, bukan melewati breaker dan membuat ulang call yang sedang dilindungi.
Transisi state memerlukan alasan yang dapat diamati
Breaker yang diam-diam open dapat membuat traffic downstream menghilang tanpa menjelaskan perubahan tersebut. Secara operasional, transisi state itu sendiri merupakan event yang layak diekspos.
Observasi yang berguna mencakup state saat ini, jumlah transisi, jumlah call yang ditolak, hasil probe, serta kegagalan terklasifikasi yang berkontribusi pada state open. Metric sebaiknya menghindari label dengan cardinality tanpa batas, terutama jika scope breaker menyertakan identifier dinamis.
Hasil breaker juga perlu dapat dibedakan dari hasil langsung dependency. Call yang ditolak karena breaker open tidak pernah menghubungi dependency. Mencatatnya sebagai kegagalan remote tambahan akan mendistorsi metric dependency maupun statistik breaker.
Log dapat mencatat transisi alih-alih setiap call yang ditolak ketika volume penolakan tinggi. Transisi membawa nilai diagnostik lebih besar dan mencegah outage dependency berubah menjadi outage logging.
Breaker membatasi amplifikasi, bukan menjamin pemulihan
Circuit breaker paling efektif ketika call berkelanjutan selama kegagalan akan memakai resource langka atau menambah tekanan pada dependency yang gagal. Nilainya berasal dari perubahan bukti kegagalan terbaru menjadi state admission lokal sementara.
State tersebut memiliki biaya. Breaker dapat menolak call setelah dependency pulih tetapi sebelum probe berikutnya. Scope yang buruk dapat mengikat operasi yang tidak berkaitan. Threshold yang terlalu sensitif dapat berosilasi antar-state. Kebijakan half-open yang terlalu longgar dapat menciptakan lonjakan traffic saat pemulihan.
Konsekuensi tersebut berasal dari mekanismenya dan bukan alasan untuk memperlakukan circuit breaker sebagai switch resilience generik. Breaker memerlukan klasifikasi kegagalan, kebijakan sampling, scope state, interval open, probe budget, dan model transisi yang dapat diamati sesuai jalur call yang dilindungi.
Batas utamanya sederhana: setelah hasil terbaru melewati kondisi kegagalan yang dikonfigurasi, percobaan remote normal berhenti selama suatu periode. Traffic pemulihan kembali melalui gate yang terkontrol. Batas ini mengurangi seberapa agresif satu dependency yang gagal dapat menghabiskan resource pada service yang memanggilnya.