Programming
Circuit Breaker
Pola circuit breaker untuk menangani kegagalan layanan jarak jauh β mencegah cascading failure dengan tiga state: Closed, Open, Half-open.
Versi Bahasa Indonesia. Baca dalam Bahasa Inggris
Latar Belakang
- Ada masalah ketika panggilan ke layanan jarak jauh gagal biasanya karena jaringan lambat, timeout, dll.
- Masalah ini biasanya diperbaiki dengan strategi retry pattern di mana pemanggil akan mencoba kembali memanggil layanan jarak jauh (dapat menambahkan backoff juga).
- Tetapi terkadang gagal karena sesuatu yang membutuhkan waktu lebih lama untuk diperbaiki.
- Maka retry pattern di sini akan sia-sia karena akan menghabiskan sumber daya pemanggil.
- Selain itu jika layanan sangat sibuk, ini dapat menciptakan cascading failure.
- Contoh:
- Request masuk dari pengguna ke layanan kita.
- Kemudian layanan kita perlu melakukan request eksternal ke API pihak ketiga.
- Tetapi karena suatu masalah, request timeout setelah
10s. - Responsnya timeout dan kita memiliki retry pattern yang akan mencoba ulang request maksimal 5 kali.
- Ini akan membuat request pengguna macet setidaknya selama
50s. - Bayangkan jika layanan kita sangat sibuk dan menangani ribuan request setiap detik.
- Ini dapat menyebabkan sumber daya terkunci oleh setidaknya
50.000request yang dapat menyebabkan cascading failure.
Solusi
Circuit Breaker bertindak sebagai proxy untuk aplikasi yang mungkin gagal. Proxy harus memantau jumlah kegagalan terbaru yang terjadi. Dan menggunakan informasi itu untuk memutuskan apakah akan mengizinkan operasi atau langsung mengembalikan error.
3 Status dari circuit breaker pattern:
- Closed: Status normal, di mana semua request diizinkan melewati ke layanan.
- Open: Circuit breaker menolak semua request ke layanan untuk mencegah kegagalan lebih lanjut.
- Half-open: Circuit breaker mengizinkan sejumlah terbatas request untuk melewati ke layanan untuk menguji apakah sudah berfungsi kembali.
Manfaat:
- Dapat mencegah aplikasi berulang kali mencoba mengeksekusi operasi yang kemungkinan akan gagal.
- Memungkinkan untuk melanjutkan tanpa menunggu.
- Mencegah pemborosan sumber daya CPU dan Memori.
Contoh
Menggunakan Library Sony
Berikut adalah contoh penggunaan circuit breaker dari library populer sony/gobreaker.
package main
import (
"fmt"
"log"
"time"
"github.com/sony/gobreaker/v2"
)
// Simulasi layanan eksternal
func callExternalService() (string, error) {
// Simulasi kegagalan acak
if time.Now().Unix()%2 == 0 {
return "", fmt.Errorf("service unavailable")
}
return "Success: Data retrieved", nil
}
// Bungkus panggilan layanan eksternal dengan Circuit Breaker
func externalServiceWithCircuitBreaker(cb *gobreaker.CircuitBreaker[string]) (string, error) {
// Eksekusi fungsi yang dilindungi circuit breaker
result, err := cb.Execute(func() (string, error) {
return callExternalService()
})
if err != nil {
return "", err
}
return result, nil
}
func main() {
// Konfigurasi Circuit Breaker
cbSettings := gobreaker.Settings{
Name: "ExternalServiceCB",
MaxRequests: 3, // Izinkan 3 request di half-open state
Interval: 10 * time.Second, // Reset state setelah 10 detik
Timeout: 5 * time.Second, // Waktu tunggu sebelum transisi ke half-open
ReadyToTrip: func(counts gobreaker.Counts) bool {
// Buka circuit ketika kegagalan melebihi 50% dari total request
failureRatio := float64(counts.TotalFailures) / float64(counts.Requests)
return counts.Requests >= 5 && failureRatio >= 0.5
},
}
circuitBreaker := gobreaker.NewCircuitBreaker[string](cbSettings)
// Simulasi panggilan periodik ke layanan eksternal
for i := 0; i < 10; i++ {
result, err := externalServiceWithCircuitBreaker(circuitBreaker)
if err != nil {
log.Printf("Request %d: Circuit Breaker Triggered - %v", i+1, err)
} else {
log.Printf("Request %d: %s", i+1, result)
}
time.Sleep(1 * time.Second)
}
}Edit on GitHub
Last updated on