

package main
import (
"fmt"
"github.com/afex/hystrix-go/hystrix"
"math/rand"
"sync"
"time"
)
type Product struct {
ID int
Title string
Price int
}
func getProduct() (Product, error) {
r := rand.Intn(10)
if r < 6 { //模擬api卡頓和超時效果
time.Sleep(time.Second * 10)
}
return Product{
ID: 101,
Title: "Golang從入門到精通",
Price: 12,
}, nil
}
func RecProduct() (Product, error) {
return Product{
ID: 999,
Title: "推薦商品",
Price: 120,
}, nil
}
func main() {
rand.Seed(time.Now().UnixNano())
configA := hystrix.CommandConfig{ //創建一個hystrix的config
Timeout: 3000, //command運行超過3秒就會報超時錯誤,並且在一個統計窗口內處理的請求數量達到閾值會調用我們傳入的降級回調函數
MaxConcurrentRequests: 5, //控制最大並發數為5,並且在一個統計窗口內處理的請求數量達到閾值會調用我們傳入的降級回調函數
RequestVolumeThreshold: 5, //判斷熔斷的最少請求數,默認是5;只有在一個統計窗口內處理的請求數量達到這個閾值,才會進行熔斷與否的判斷
ErrorPercentThreshold: 5, //判斷熔斷的閾值,默認值5,表示在一個統計窗口內有50%的請求處理失敗,比如有20個請求有10個以上失敗了會觸發熔斷器短路直接熔斷服務
SleepWindow: int(time.Second * 10), //熔斷器短路多久以后開始嘗試是否恢復,這里設置的是10
}
hystrix.ConfigureCommand("get_prod", configA) //hystrix綁定command
c, _, _ := hystrix.GetCircuit("get_prod") //返回值有三個,第一個是熔斷器指針,第二個是bool表示是否能夠取到,第三個是error
resultChan := make(chan Product, 1)
wg := &sync.WaitGroup{}
for i := 0; i < 20; i++ {
go func() {
wg.Add(1)
defer wg.Done()
errs := hystrix.Do("get_prod", func() error { //使用hystrix來講我們的操作封裝成command,hystrix返回值是一個chan error
p, _ := getProduct() //這里會隨機延遲0-4秒
fmt.Println("hello")
resultChan <- p
return nil //這里返回的error在回調中可以獲取到,也就是下面的e變量
}, func(e error) error {
fmt.Println("hello")
rcp, err := RecProduct() //推薦商品,如果這里的err不是nil,那么就會忘errs中寫入這個err,下面的select就可以監控到
resultChan <- rcp
return err
})
if errs != nil { //這里errs是error接口,但是使用hystrix.Go異步執行時返回值是chan error各個協程的錯誤都放到errs中
fmt.Println(errs)
} else {
select {
case prod := <-resultChan:
fmt.Println(prod)
}
}
fmt.Println(c.IsOpen()) //判斷熔斷器是否打開,一旦打開所有的請求都會走fallback
fmt.Println(c.AllowRequest()) //判斷是否允許請求服務,一旦打開
}()
}
wg.Wait()
}
下面是輸出,可以看到hello執行的次數明顯沒有200次,所有的輸出加起來也只有89行,但是我們開了200個協程,也就是說熔斷器直接熔斷服務了,一部分請求直接被拒絕了,只有等待我們設置的10s后再把熔斷器設置成半打開狀態,再次執行根據結果判斷熔斷器應該設置成什么狀態
hello
hello
hello
hello
hello
hello
hello
hello
hello
hello
{999 推薦商品 120}
true
false
hello
hello
hello
hello
{101 Golang從入門到精通 12}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
hello
hello
hello
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{101 Golang從入門到精通 12}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
hello
hello
hello
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false
{999 推薦商品 120}
true
false