Lompat ke konten
dokumentasi.id
Commit ecba1e8
v2
Star2,8 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

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-37. Kesetaraan dengan interface dijaga oleh var _ heimdall.Client = (*Client)(nil) hystrix/hystrix_client.go:51-52.

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-80. 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-92. 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.
Fig. 1: Perakitan konfigurasi commandOption 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-49. Satu-satunya jalan mengisinya adalah WithCommandName hystrix/options.go:16-21. Tanpa opsi itu, ConfigureCommand menerima 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-77.

Field ClientKonstanta defaultNilaiField CommandConfig
hystrixTimeoutdefaultHystrixTimeout30 * time.SecondTimeout dalam milidetik
maxConcurrentRequestsdefaultMaxConcurrentRequests100MaxConcurrentRequests
requestVolumeThresholddefaultRequestVolumeThreshold10RequestVolumeThreshold
sleepWindowdefaultSleepWindow500 * time.MillisecondSleepWindow dalam milidetik
errorPercentThresholddefaultErrorPercentThreshold25ErrorPercentThreshold
retryCountdefaultHystrixRetryCount0dipakai loop Do, bukan hystrix
retrierheimdall.NewNoRetrier()tanpa retrydipakai loop Do, bukan hystrix

Nilai pada kolom ketiga diambil langsung dari blok konstanta hystrix/hystrix_client.go:39-49.

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-35. 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-49.

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.
Fig. 2: Siklus circuit breakerAmbang 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:6. 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-207. Dengan nilai default retryCount 0, loop hanya berjalan sekali hystrix/hystrix_client.go:39-49. 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.
Fig. 3: Jalur satu request di dalam hystrix commandhystrixDo 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-241. 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-232.

Sentinel itu didefinisikan sekali sebagai errors.New("server returned status code to retry") hystrix/hystrix_client.go:51-52. 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-238. Do kemudian mengubah sentinel itu menjadi response tanpa error hystrix/hystrix_client.go:209-217. 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-86. Method Update menjumlahkan setiap field MetricResult ke satu nilai total hystrix/helper_test.go:28-46.

Field MetricResultArti dari namanya
Attemptsjumlah run func yang dijalankan
Successes, Errors, Failureshasil run func
Timeoutsrun func melewati CommandConfig.Timeout
Rejectsrequest ditolak karena batas MaxConcurrentRequests
ShortCircuitsrequest tidak sampai ke run func karena circuit terbuka
FallbackSuccesses, FallbackFailureshasil pemanggilan fallbackFunc
ContextCanceled, ContextDeadlineExceededcontext request selesai lebih dulu
TotalDuration, RunDuration, ConcurrencyInUsedurasi dan concurrency yang tercatat

delayedCancelDoer membuat Do menunggu r.Context().Done() sebelum mengembalikan error context hystrix/helper_test.go:88-96. Test TestHystrixHTTPClientDoContextCancelled memakainya dan mengharapkan ContextCanceled bernilai 1 sementara Failures nol hystrix/hystrix_client_test.go:695-732, jadi pembatalan context tidak dihitung sebagai kegagalan yang menekan circuit. Perilaku fallbackFunc dibahas terpisah di halaman Option dan Fallback hystrix.