go-kit 微服務 服務熔斷(hystrix-go 實現)


go-kit 微服務 服務熔斷(hystrix-go 實現)

  • 對客戶端請求login方法添加熔斷

Hystrix

  • 在微服務架構中,每個服務都是相互關聯的,比如我們下單服務和扣錢服務是分開的,現在扣錢服務出現的bug不能正常服務
  • Hystrix可以讓我們在在微服務架構中對服務間的調用進行控制,加入一些調用延遲或者服務降級的容錯機制。

Hystrix的設計原則

  • 對依賴服務調用時出現的調用延遲和調用失敗進行控制和容錯保護
  • 在復雜的分布式系統中,阻止某一個依賴服務的故障在整個系統中蔓延
  • 提供fail-fast(快速失敗)和快速恢復的支持
  • 提供fallback優雅降級的支持
  • 支持近實時的監控、報警以及運維操作

編寫Hystrix類

import (
    "errors"
    "github.com/afex/hystrix-go/hystrix"
    "sync"
)

var config = hystrix.CommandConfig{
    Timeout:                5000, //執行command的超時時間(毫秒)
    MaxConcurrentRequests:  8,    //command的最大並發量
    SleepWindow:            1000, //過多長時間,熔斷器再次檢測是否開啟。單位毫秒
    ErrorPercentThreshold:  30,   //錯誤率 請求數量大於等於RequestVolumeThreshold並且錯誤率到達這個百分比后就會啟動
    RequestVolumeThreshold: 5,    //請求閾值(一個統計窗口10秒內請求數量)  熔斷器是否打開首先要滿足這個條件;這里的設置表示至少有5個請求才進行ErrorPercentThreshold錯誤百分比計算
}

type runFunc func() error

type Hystrix struct {
    loadMap  *sync.Map //儲存每個調用函數對應的 Hystrix
    fallback string   //降級信息
}

func NewHystrix(msg string) *Hystrix {
    return &Hystrix{
        loadMap:  new(sync.Map),
        fallback: msg,
    }
}

func (s *Hystrix) Run(name string, run runFunc) error {
    if _, ok := s.loadMap.Load(name); !ok {
        hystrix.ConfigureCommand(name, config)
        s.loadMap.Store(name, name)
    }
    //name 為執行的命令名稱
    //run  我們要執行的函數
    //fallback:run運行過程中發生錯誤時的回調方法
    err := hystrix.Do(name, func() error {
        return run()
    }, func(err error) error {
        //fmt.Println("運行 run 方法錯誤", err)
        return errors.New(s.fallback)
    })
    if err != nil {
        return err
    }
    return nil
}

添加Hystrix到調用客戶端

  • 這里為了展示Hystrix的狀態去掉了一些日志信息
hy := utils.NewHystrix("調用錯誤服務降級")
cbs, _, _ := hystrix.GetCircuit("login")
for i := 0; i < 100; i++ {
    time.Sleep(time.Millisecond * 100)
    userAgent, err := client.UserAgentClient()
    if err != nil {
        t.Error(err)
        return
    }
err = hy.Run("login", func() error {
    _, err := userAgent.Login(context.Background(), &pb.Login{
        Account:  "hwholiday",
        Password: "123456",
    })
    if err != nil {
        return err
    }
        //fmt.Println(ack.Token)
        return nil
    })
fmt.Println("熔斷器開啟狀態:", cbs.IsOpen(), "請求是否允許:", cbs.AllowRequest())
    if err != nil {
        t.Log(err)
    }
}

去掉服務端的請求限制功能

func NewEndPointServer(svc Service, limit *rate.Limiter) EndPointServer {
    var loginEndPoint endpoint.Endpoint
    {
        loginEndPoint = MakeLoginEndPoint(svc)
        //loginEndPoint = NewGolangRateAllowMiddleware(limit)(loginEndPoint)
    }
    return EndPointServer{LoginEndPoint: loginEndPoint}
}

模擬服務器錯誤功能

if in.Account != "hwholiday" || in.Password != "123456" {
    err = errors.New("用戶信息錯誤")
    return
}
//模擬耗時
//rand.Seed(time.Now().UnixNano())
//sl := rand.Int31n(10-1) + 1
//time.Sleep(time.Duration(sl) * time.Millisecond * 100)
//模擬錯誤
if rand.Intn(10) > 3 {
    err = errors.New("服務器運行錯誤")
    return
}
ack = &pb.LoginAck{}

運行

  • 運行 TestNewUserAgentClient 方法 (調用Login接口100次)

     

熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
s.LoginEndPoint rpc error: code = Unknown desc = 服務器運行錯誤
s.LoginEndPoint rpc error: code = Unknown desc = 服務器運行錯誤
s.LoginEndPoint rpc error: code = Unknown desc = 服務器運行錯誤
s.LoginEndPoint rpc error: code = Unknown desc = 服務器運行錯誤 (previously: rpc error: code = Unknown desc = 服務器運行錯誤; rpc error: code = Unknown desc = 服務器運行錯誤)
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: true 請求是否允許: false
熔斷器開啟狀態: false 請求是否允許: true
s.LoginEndPoint rpc error: code = Unknown desc = 服務器運行錯誤
熔斷器開啟狀態: false 請求是否允許: true


## 結語
+ 我們可以看到Hystrix的狀態從 打開 ->關閉 -> 打開
+ Hystrix的用法還有很多,這里只展示簡單的使用,更加高級的功能歡迎大家一起討論
+ 歡迎添加QQ一起討論


### [完整代碼地址](https://github.com/hwholiday/learning_tools/tree/master/go-kit/v8)


作者:hwholiday
鏈接:https://www.jianshu.com/p/15975197c2be
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM