Go 每日一庫之 hystrix-go
Hystrix 是一個延遲和容錯庫,旨在隔離對遠程系統(tǒng)、服務(wù)和第三方庫的訪問點,防止級聯(lián)故障,并在故障不可避免的復(fù)雜分布式系統(tǒng)中實現(xiàn)彈性。
我認為程序員定義的回退(fallbacks)和自適應(yīng)健康監(jiān)控的 Hystrix 模式適用于任何分布式系統(tǒng)。Goroutines和channels是很好的并發(fā)原語,但不能直接幫助我們的應(yīng)用程序在故障期間保持可用。
hystrix-go[2] 旨在讓 Go 程序員輕松構(gòu)建具有與基于 Java 的 Hystrix 庫類似的執(zhí)行語義的應(yīng)用程序。
有關(guān) Hystrix 工作原理的更多信息,請參閱Java Hystrix wiki[3]
有關(guān) API 文檔,請參閱pkg.go.dev[4]
如何使用
import "github.com/afex/hystrix-go/hystrix"
將代碼作為 Hystrix 命令執(zhí)行
定義依賴于外部系統(tǒng)的應(yīng)用程序邏輯,將函數(shù)傳遞給hystrix.Go. 當(dāng)該系統(tǒng)正常健康時,會執(zhí)行此方法。
hystrix.Go("my_command", func() error {
// talk to other services
return nil
}, nil)
定義回退行為
如果你希望在服務(wù)中斷期間執(zhí)行代碼,可以將第二個函數(shù)傳遞給hystrix.Go. 理想情況下,這兒的邏輯可以使應(yīng)用程序優(yōu)雅地處理不可用的外部服務(wù)。
當(dāng)代碼返回一個錯誤時,或者當(dāng)它基于各種健康檢查[5]無法完成時,就會觸發(fā)此事件。
hystrix.Go("my_command", func() error {
// talk to other services
return nil
}, func(err error) error {
// do this when services are down
return nil
})
等待輸出
調(diào)用hystrix.Go就像啟動一個 goroutine,你會收到一個可以select監(jiān)控的error channel。
output := make(chan bool, 1)
errors := hystrix.Go("my_command", func() error {
// talk to other services
output <- true
return nil
}, nil)
select {
case out := <-output:
// success
case err := <-errors:
// failure
}
同步 API
由于調(diào)用命令并立即等待它完成是種常見的模式,因此hystrix提供了一個同步API。hystrix.Do函數(shù)返回一個錯誤。
err := hystrix.Do("my_command", func() error {
// talk to other services
return nil
}, nil)
配置設(shè)置
在應(yīng)用程序啟動期間,你可以調(diào)用hystrix.ConfigureCommand()來調(diào)整每個命令的設(shè)置。
hystrix.ConfigureCommand("my_command", hystrix.CommandConfig{
Timeout: 1000,
MaxConcurrentRequests: 100,
ErrorPercentThreshold: 25,
})
你也可以使用hystrix.Configure(),它接受一個map[string]CommandConfig的map。
如何啟用儀表板指標(biāo)
在你的 main.go 中,在端口上注冊事件流 HTTP 處理程序并在 goroutine 中啟動它。一旦你為Hystrix 儀表板[6]配置了渦輪機以開始流式傳輸事件,你的命令將自動開始出現(xiàn)。
在 main.go 中,在端口上注冊事件流 HTTP 處理程序,并在 goroutine 中啟動它。一旦為 Hystrix 儀表板配置了渦輪機(turbine)以啟動流事件,命令將自動開始顯示。
hystrixStreamHandler := hystrix.NewStreamHandler()
hystrixStreamHandler.Start()
go http.ListenAndServe(net.JoinHostPort("", "81"), hystrixStreamHandler)
將circuit指標(biāo)發(fā)送到 Statsd
c, err := plugins.InitializeStatsdCollector(&plugins.StatsdCollectorConfig{
StatsdAddr: "localhost:8125",
Prefix: "myapp.hystrix",
})
if err != nil {
log.Fatalf("could not initialize statsd client: %v", err)
}
metricCollector.Registry.Register(c.NewStatsdCollector)
FAQ
如果我的運行函數(shù)發(fā)生了panic會怎么樣?hystrix-go 會觸發(fā)回退嗎?
不,hystrix-go 不使用recover(),所以panic會像平常一樣殺死進程。
如何構(gòu)建和測試
安裝 vagrant 和 VirtualBox 將hystrix-go 存儲庫clone下來 在 hystrix-go 目錄中,運行 vagrant up,然后vagrant sshcd /go/src/github.com/afex/hystrix-gogo test ./...
相關(guān)的庫
談到熔斷限流的話題,想必大家也想到了阿里開源的面向分布式、多語言異構(gòu)化服務(wù)架構(gòu)的流量治理組件 sentinel-go[7] ,關(guān)于sentinel-go中滑動窗口的設(shè)計,感興趣的同學(xué)可以查看深度解析Sentinel Go 滑動窗口統(tǒng)計結(jié)構(gòu)的設(shè)計。
另外關(guān)于hstrix-go源碼分析的章節(jié),可以查看小土之前轉(zhuǎn)發(fā)阿松的微服務(wù)架構(gòu)下的熔斷框架:hystrix-go。
參考資料
Hystrix: https://github.com/Netflix/Hystrix
[2]hystrix-go: https://github.com/afex/hystrix-go/
[3]Java Hystrix wiki: https://github.com/Netflix/Hystrix/wiki
[4]pkg.go.dev: https://pkg.go.dev/github.com/afex/hystrix-go/hystrix
[5]各種健康檢查: https://github.com/Netflix/Hystrix/wiki/How-it-Works
[6]Hystrix 儀表板: https://github.com/Netflix/Hystrix/tree/master/hystrix-dashboard
[7]sentinel-go: https://github.com/alibaba/sentinel-golang
推薦閱讀
