欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go-zero熔斷機制組件Breaker接口定義使用解析

 更新時間:2023年05月29日 09:03:12   作者:Keson  
這篇文章主要為大家介紹了go-zero熔斷機制組件Breaker接口定義使用解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

概述

熔斷機制是一種微服務(wù)保護機制。當(dāng)某個微服務(wù)出現(xiàn)故障或者異常時,通過熔斷機制,可以防止故障或異常擴散到整個微服務(wù)系統(tǒng)中,從而避免整個微服務(wù)系統(tǒng)被拖垮,熔斷機制的大致流程是(以下流程基于 go-zero 熔斷器為背景):

  • 指標(biāo)采集:熔斷器通過不斷監(jiān)測服務(wù)的請求和響應(yīng)來收集指標(biāo),這些指標(biāo)包含但不限于響應(yīng)時間,錯誤率,超時率等。
  • 閾值設(shè)定:熔斷器通過指標(biāo)來計算出閾值,當(dāng)指標(biāo)超過閾值時,熔斷器會打開。
  • 熔斷狀態(tài)控制:一般熔斷器都有3個狀態(tài),熔斷開啟,熔斷恢復(fù),熔斷半開:
    3.1 熔斷開啟:當(dāng)服務(wù)的指標(biāo)超過設(shè)定的閾值時,熔斷機制將服務(wù)切換到熔斷狀態(tài)。在熔斷狀態(tài)下,服務(wù)將停止接收新的請求,并立即返回錯誤響應(yīng),而不會進行實際的業(yè)務(wù)邏輯處理。
    3.2 熔斷恢復(fù):一旦服務(wù)進入熔斷狀態(tài),熔斷機制會設(shè)定一個恢復(fù)時間窗口,在該窗口內(nèi)不再接收新的請求。在這段時間內(nèi),系統(tǒng)可以嘗試修復(fù)服務(wù)或等待服務(wù)自動恢復(fù)。
    3.3 半開狀態(tài):在熔斷恢復(fù)時間窗口結(jié)束后,熔斷機制將服務(wù)切換到半開狀態(tài)。在半開狀態(tài)下,系統(tǒng)會嘗試發(fā)送一部分請求給服務(wù),以檢測其是否已經(jīng)恢復(fù)正常。如果這些請求成功響應(yīng),那么服務(wù)將被認為是恢復(fù)正常,并繼續(xù)接收新的請求。否則,服務(wù)將重新進入熔斷狀態(tài)。
    但在 go-zero 中并非完全如此,go-zero 中只有熔斷關(guān)閉,熔斷觸發(fā)開啟狀態(tài),為什么是熔斷觸發(fā)開啟,在 go-zero 中,熔斷指標(biāo)達到設(shè)定閾值后,并不是直接攔截所有請求,而是有一定的概率攔截請求,這并不是說他就沒有熔斷恢復(fù)和熔斷半開狀態(tài),只是 go-zero 中熔斷器將這 2 個狀態(tài)巧妙的用滑動窗口來實現(xiàn)了。

go-zero 熔斷器時序圖

源碼解析

在 go-zero 中,Breaker 是一個接口,其接口定義如下:

Breaker interface {
   Name() string
   Allow() (Promise, error)
   Do(req func () error) error
   DoWithAcceptable(req func () error, acceptable Acceptable) error
   DoWithFallback(req func () error, fallback func (err error) error) error
   DoWithFallbackAcceptable(req func () error, fallback func (err error) error, acceptable Acceptable) error
}

Breaker 接口定義了 6 個方法,提供了 2 中對熔斷器控制執(zhí)行的機制:

Allow 方法拋出了一個 Promise 句柄,允許用戶自行對熔斷指標(biāo)進行控制,采集指標(biāo)可以根據(jù)用戶需求選擇請求時延、錯誤碼等,且熔斷觸發(fā)后需要執(zhí)行的邏輯也有用戶自行控制。如 go-zero
中 rest 中熔斷中間件的用法:

func BreakerHandler(method, path string, metrics *stat.Metrics) func(http.Handler) http.Handler {
 brk := breaker.NewBreaker(breaker.WithName(strings.Join([]string{method, path}, breakerSeparator)))
 return func(next http.Handler) http.Handler {
     return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
         promise, err := brk.Allow()// 熔斷執(zhí)行邏輯,用戶自行控制
         if err != nil {
             metrics.AddDrop()
             logx.Errorf("[http] dropped, %s - %s - %s",
                 r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent())
             w.WriteHeader(http.StatusServiceUnavailable)
             return
         }
         cw := &response.WithCodeResponseWriter{Writer: w}
         defer func() {// 熔斷指標(biāo)采集,用戶自行控制
             if cw.Code < http.StatusInternalServerError {
                 promise.Accept()
             } else {
                 promise.Reject(fmt.Sprintf("%d %s", cw.Code, http.StatusText(cw.Code)))
             }
         }()
         next.ServeHTTP(cw, r)
     })
 }
}
  • DoXxx 方法則是另一個中熔斷器控制機制,其只能通過錯誤碼來進行指標(biāo)采集,當(dāng)然,用戶是可以根據(jù)錯誤碼來控制哪些錯誤碼是要加入到指標(biāo)里面的,除此外,
    函數(shù)執(zhí)行體也是用用戶告知到熔斷器中,熔斷器會在熔斷未觸發(fā)的情況下執(zhí)行函數(shù)體,如果熔斷觸發(fā),則會執(zhí)行熔斷器中的邏輯。如返回熔斷錯誤。

DoXxx 方法在底層邏輯最終都是調(diào)用一個基礎(chǔ)方法,只是根據(jù)入?yún)⒌牟煌┞读瞬煌暮瘮?shù):

doReq(req func() error, fallback func(err error) error, acceptable Acceptable) error

我們來看一下 doReq 方法的一個流程圖:

func (b *googleBreaker) doReq(req func() error, fallback func(err error) error, acceptable Acceptable) error {
    // 判斷熔斷器是否開啟
    if err := b.accept(); err != nil {
        if fallback != nil {
            return fallback(err)
        }
        return err
    }
    // 函數(shù)異常退出,上報失敗指標(biāo)
    defer func() {
        if e := recover(); e != nil {
            b.markFailure()
            panic(e)
        }
    }()
    // 執(zhí)行用戶函數(shù),并通過函數(shù)執(zhí)行返回的錯誤信息由用戶判斷是否為可接受的錯誤
    // 上報指標(biāo)
    err := req()
    if acceptable(err) {
        b.markSuccess()
    } else {
        b.markFailure()
    }
    return err
}

熔斷器狀態(tài)判斷

判斷熔斷器是否開啟是根據(jù)當(dāng)前窗口的歷史指標(biāo)來計算的,這里采用了 google SRE 里面的丟棄比例算法,當(dāng)丟棄比例為0時,則無需觸發(fā)熔斷,否則
隨機觸發(fā)熔斷機制。

func (b *googleBreaker) accept() error {
    accepts, total := b.history()
    weightedAccepts := b.k * float64(accepts)
    // https://landing.google.com/sre/sre-book/chapters/handling-overload/#eq2101
    dropRatio := math.Max(0, (float64(total-protection)-weightedAccepts)/float64(total+1))
    if dropRatio <= 0 {
        return nil
    }
    if b.proba.TrueOnProba(dropRatio) {
        return ErrServiceUnavailable
    }
    return nil
}
func (b *googleBreaker) history() (accepts, total int64) {
   b.stat.Reduce(func(b *collection.Bucket) {
      accepts += int64(b.Sum)
      total += b.Count
   })
    return
}

指標(biāo)上報

指標(biāo)上報是將用戶執(zhí)行后的請求錯誤返回給用戶,用戶可以根據(jù)錯誤碼指定改錯誤碼是否納入失敗指標(biāo)

// 標(biāo)記成功一次
func (b *googleBreaker) markSuccess() {
    b.stat.Add(1)
}
// 標(biāo)記失敗一次
func (b *googleBreaker) markFailure() {
    b.stat.Add(0)
}

總結(jié)

熔斷器的實現(xiàn)起始就是一個指標(biāo)采集+指標(biāo)計算的過程,然后用戶可以根據(jù)指標(biāo)計算結(jié)果來決定是否觸發(fā)熔斷,其中難點還是在于指標(biāo)統(tǒng)計過程,這個過程是用滑動窗口來進行指標(biāo)采集的,關(guān)于滑動窗口算法這里就不做過多的介紹了。

以上就是go-zero組件Breaker的詳細內(nèi)容,更多關(guān)于go-zero 組件Breaker的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文教你Golang如何正確關(guān)閉通道

    一文教你Golang如何正確關(guān)閉通道

    Go在通道這一塊,沒有內(nèi)置函數(shù)判斷通道是否已經(jīng)關(guān)閉,也沒有可以直接獲取當(dāng)前通道數(shù)量的方法,因此如果對通道進行了錯誤的使用,將會直接引發(fā)系統(tǒng)?panic,這是一件很危險的事情,下面我們就來學(xué)習(xí)一下如何正確關(guān)閉通道吧
    2023-10-10
  • golang中拿slice當(dāng)queue和拿list當(dāng)queue使用分析

    golang中拿slice當(dāng)queue和拿list當(dāng)queue使用分析

    這篇文章主要為大家介紹了golang?中拿slice當(dāng)queue和拿list當(dāng)queue使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • Golang中的包及包管理工具go?mod詳解

    Golang中的包及包管理工具go?mod詳解

    這篇文章主要介紹了Golang中的包及包管理工具go?mod,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 利用Go語言實現(xiàn)二叉搜索樹

    利用Go語言實現(xiàn)二叉搜索樹

    二叉樹是一種常見并且非常重要的數(shù)據(jù)結(jié)構(gòu),在很多項目中都能看到二叉樹的身影,當(dāng)然它也有很多變種,本文要介紹的是二叉搜索樹的實現(xiàn),希望對大家有所幫助
    2023-07-07
  • GO 反射對性能的影響分析

    GO 反射對性能的影響分析

    這篇文章主要為大家介紹了GO 反射對性能的影響分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 淺談用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法

    淺談用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法

    這篇文章主要介紹了用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 一文掌握go的sync.RWMutex鎖

    一文掌握go的sync.RWMutex鎖

    這篇文章主要介紹了一文掌握go的sync.RWMutex鎖,本文是為了在面試中能快速口述RW鎖,并非為了完整解答RW鎖的機制,需要的朋友可以參考下
    2023-03-03
  • 解決Golang小數(shù)float64在實際工程中加減乘除的精度問題

    解決Golang小數(shù)float64在實際工程中加減乘除的精度問題

    這篇文章主要介紹了解決Golang小數(shù)float64在實際工程中加減乘除的精度問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • 手把手教你導(dǎo)入Go語言第三方庫

    手把手教你導(dǎo)入Go語言第三方庫

    本文主要介紹了手把手教你導(dǎo)入Go語言第三方庫,通過導(dǎo)入gin包來深入學(xué)習(xí),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 詳解Go語言中init的使用與常見應(yīng)用場景

    詳解Go語言中init的使用與常見應(yīng)用場景

    Go?中有一個特別的?init()?函數(shù),它主要用于包的初始化,這篇文章將以此為主題介紹?Go?中?init()?函數(shù)的使用和常見使用場景,希望對大家有所幫助
    2024-02-02

最新評論