6
Klien Circuit Breaker
hystrix.Client adalah implementasi heimdall.Client yang membungkus httpclient.Client di dalam satu hystrix command. Struct ini menyimpan satu *httpclient.Client, lima parameter command, satu fallbackFunc, dan tiga field retry hystrix/hystrix_client.go:21-371. Kesetaraan dengan interface dijaga oleh var _ heimdall.Client = (*Client)(nil) hystrix/hystrix_client.go:51-522.
Perakitan client dan ConfigureCommand
NewClient mengisi field dengan nilai default, menjalankan setiap Option pada struct tersebut, lalu memanggil hystrix.ConfigureCommand dengan hystrixCommandName dan hystrix.CommandConfig hystrix/hystrix_client.go:54-803. Konfigurasi command terdaftar sekali saat client dibuat; request berikutnya hanya membaca konfigurasi itu.
Nilai durasi dikonversi oleh durationToInt, yang membagi durasi dengan satuan time.Millisecond lalu menahan hasilnya pada maxInt hystrix/hystrix_client.go:82-924. Komentar di fungsi itu menyebut overflow tidak bisa dilaporkan sebagai error tanpa mengubah API NewClient.
graph LR
OPT["Option: WithCommandName, WithHystrixTimeout, WithMaxConcurrentRequests, ..."] --> NC["NewClient"]
DEF["default: 30s, 100, 10, 500ms, 25"] --> NC
NC --> CFG["hystrix.ConfigureCommand"]
CFG --> CMD["CommandConfig per hystrixCommandName"]
CMD --> DOC["hystrix.DoC di hystrixDo"]
style OPT fill:#2d7d46,color:#fff
style DEF fill:#8b5cf6,color:#fff
style CFG fill:#f59e0b,color:#000
style CMD fill:#336791,color:#fff
%% fig: Perakitan konfigurasi command
%% desc: Option dan nilai default mengisi struct Client, lalu NewClient mendaftarkan CommandConfig ke hystrix-go satu kali per nama command.⚠️ Tidak ada konstanta default untuk nama command hystrix/hystrix_client.go:39-495. Satu-satunya jalan mengisinya adalah
WithCommandNamehystrix/options.go:16-216. Tanpa opsi itu,ConfigureCommandmenerima string kosong, dan dua client dengan nama command yang sama akan saling menimpa konfigurasi karena yang tersimpan adalah pemanggilan terakhir.
Nilai default command
CommandConfig diisi dari lima field dengan nama yang sama seperti parameter hystrix-go: Timeout, MaxConcurrentRequests, RequestVolumeThreshold, SleepWindow, dan ErrorPercentThreshold hystrix/hystrix_client.go:71-777.
Field Client | Konstanta default | Nilai | Field CommandConfig |
|---|---|---|---|
hystrixTimeout | defaultHystrixTimeout | 30 * time.Second | Timeout dalam milidetik |
maxConcurrentRequests | defaultMaxConcurrentRequests | 100 | MaxConcurrentRequests |
requestVolumeThreshold | defaultRequestVolumeThreshold | 10 | RequestVolumeThreshold |
sleepWindow | defaultSleepWindow | 500 * time.Millisecond | SleepWindow dalam milidetik |
errorPercentThreshold | defaultErrorPercentThreshold | 25 | ErrorPercentThreshold |
retryCount | defaultHystrixRetryCount | 0 | dipakai loop Do, bukan hystrix |
retrier | heimdall.NewNoRetrier() | tanpa retry | dipakai loop Do, bukan hystrix |
Nilai pada kolom ketiga diambil langsung dari blok konstanta hystrix/hystrix_client.go:39-495.
Ada dua lapis timeout yang berbeda. WithHTTPTimeout meneruskan timeout ke httpclient.Client yang berada di dalam command, sedangkan WithHystrixTimeout mengisi hystrixTimeout yang menjadi CommandConfig.Timeout hystrix/options.go:23-358. Command dapat timeout lebih dulu daripada http.Client di dalamnya.
Siklus buka-tutup circuit
Tiga ambang menentukan perpindahan keadaan: RequestVolumeThreshold 10 dan ErrorPercentThreshold 25 memutus jalur setelah cukup banyak request gagal, sementara SleepWindow 500ms menentukan kapan satu percobaan diizinkan lagi hystrix/hystrix_client.go:39-495.
stateDiagram-v2
[*] --> Closed: NewClient memanggil ConfigureCommand
Closed --> Open: errorPercentThreshold 25 terlampaui setelah requestVolumeThreshold 10
Open --> Probe: sleepWindow 500ms lewat
Probe --> Closed: run func sukses
Probe --> Open: run func gagal atau Timeout 30s
note right of Open
run func tidak dipanggil
Rejects dan ShortCircuits naik
end note
classDef good fill:#2d7d46,color:#fff
classDef bad fill:#dc2626,color:#fff
classDef warn fill:#f59e0b,color:#000
class Closed good
class Open bad
class Probe warn
%% fig: Siklus circuit breaker
%% desc: Ambang dari CommandConfig memindahkan command dari Closed ke Open, lalu satu percobaan Probe setelah SleepWindow memutuskan apakah circuit kembali tertutup.Nama keadaan di diagram adalah penyederhanaan: repository hanya menyuplai ambang, sedangkan mesin keadaan dan penolakannya berada di paket github.com/gojek/hystrix-go/hystrix yang dideklarasikan pada go.mod:69. Yang bisa dipastikan dari repository adalah nilai ambang yang dikirim, bukan nama internal keadaan.
Satu request di dalam command
Do menjalankan loop for i := 0; i <= hhc.retryCount; i++ dan memanggil hhc.hystrixDo(request) pada setiap percobaan hystrix/hystrix_client.go:180-20710. Dengan nilai default retryCount 0, loop hanya berjalan sekali hystrix/hystrix_client.go:39-495. Rincian interval dan batas retry dibahas di halaman Siklus Request dan Retry dan Error Budget untuk Retry.
graph TD
A["Client.Do"] --> B["hhc.hystrixDo(request)"]
B --> C["hystrix.DoC: context, hystrixCommandName, run func, fallbackFunc"]
C -->|"circuit menerima"| D["run func: hhc.client.Do(request)"]
D --> E{"status code di retryableCodes atau 5xx?"}
E -->|"ya"| F["kembalikan errRetryableCode"]
E -->|"tidak"| G["kembalikan nil, response disimpan"]
C -->|"circuit menolak atau timeout"| H["error dari hystrix.DoC"]
H --> I["fallbackFunc"]
F --> J["Do: errors.Is errRetryableCode lalu return response, nil"]
G --> J
style C fill:#f59e0b,color:#000
style D fill:#2d7d46,color:#fff
style F fill:#dc2626,color:#fff
style H fill:#dc2626,color:#fff
style I fill:#8b5cf6,color:#fff
style J fill:#2d7d46,color:#fff
%% fig: Jalur satu request di dalam hystrix command
%% desc: hystrixDo menjalankan run func lewat hystrix.DoC, dan status code yang perlu diulang dipetakan menjadi errRetryableCode agar tetap terbaca oleh loop retry di Do.hystrixDo memanggil hystrix.DoC dengan context request, nama command, run func, dan hhc.fallbackFunc hystrix/hystrix_client.go:220-24111. Run func memanggil hhc.client.Do(request) dan menyimpan response, lalu mengembalikan errRetryableCode bila status code ditemukan oleh slices.BinarySearch pada retryableCodes atau bernilai 5xx hystrix/hystrix_client.go:229-23212.
Sentinel itu didefinisikan sekali sebagai errors.New("server returned status code to retry") hystrix/hystrix_client.go:51-522. Karena run func mengembalikan error, hystrix menghitung 5xx sebagai kegagalan command. Namun hystrixDo sengaja tidak meneruskan sentinel tersebut sebagai error, dengan komentar tentang data race hystrix/hystrix_client.go:236-23813. Do kemudian mengubah sentinel itu menjadi response tanpa error hystrix/hystrix_client.go:209-21714. Dengan begitu response 5xx tetap sampai ke pemanggil sambil ikut menekan rasio error circuit.
Membaca keadaan circuit dari metrics
Collector di helper_test.go dipakai test untuk membaca keadaan circuit per command. newSimpleMetricRegistry mendaftarkan Register ke metricCollector.Registry, sehingga setiap nama command memperoleh satu collector dan GetMetrics(cmdName) mengembalikan totalnya hystrix/helper_test.go:55-8615. Method Update menjumlahkan setiap field MetricResult ke satu nilai total hystrix/helper_test.go:28-4616.
Field MetricResult | Arti dari namanya |
|---|---|
Attempts | jumlah run func yang dijalankan |
Successes, Errors, Failures | hasil run func |
Timeouts | run func melewati CommandConfig.Timeout |
Rejects | request ditolak karena batas MaxConcurrentRequests |
ShortCircuits | request tidak sampai ke run func karena circuit terbuka |
FallbackSuccesses, FallbackFailures | hasil pemanggilan fallbackFunc |
ContextCanceled, ContextDeadlineExceeded | context request selesai lebih dulu |
TotalDuration, RunDuration, ConcurrencyInUse | durasi dan concurrency yang tercatat |
delayedCancelDoer membuat Do menunggu r.Context().Done() sebelum mengembalikan error context hystrix/helper_test.go:88-9617. Test TestHystrixHTTPClientDoContextCancelled memakainya dan mengharapkan ContextCanceled bernilai 1 sementara Failures nol hystrix/hystrix_client_test.go:695-73218, jadi pembatalan context tidak dihitung sebagai kegagalan yang menekan circuit. Perilaku fallbackFunc dibahas terpisah di halaman Option dan Fallback hystrix.