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

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

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

概述

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

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

go-zero 熔斷器時(shí)序圖

源碼解析

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

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 個(gè)方法,提供了 2 中對(duì)熔斷器控制執(zhí)行的機(jī)制:

Allow 方法拋出了一個(gè) Promise 句柄,允許用戶自行對(duì)熔斷指標(biāo)進(jìn)行控制,采集指標(biāo)可以根據(jù)用戶需求選擇請(qǐng)求時(shí)延、錯(cuò)誤碼等,且熔斷觸發(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 方法則是另一個(gè)中熔斷器控制機(jī)制,其只能通過(guò)錯(cuò)誤碼來(lái)進(jìn)行指標(biāo)采集,當(dāng)然,用戶是可以根據(jù)錯(cuò)誤碼來(lái)控制哪些錯(cuò)誤碼是要加入到指標(biāo)里面的,除此外,
    函數(shù)執(zhí)行體也是用用戶告知到熔斷器中,熔斷器會(huì)在熔斷未觸發(fā)的情況下執(zhí)行函數(shù)體,如果熔斷觸發(fā),則會(huì)執(zhí)行熔斷器中的邏輯。如返回熔斷錯(cuò)誤。

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

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

我們來(lái)看一下 doReq 方法的一個(gè)流程圖:

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

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

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

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)上報(bào)

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

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

總結(jié)

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

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

相關(guān)文章

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

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

    Go在通道這一塊,沒(méi)有內(nèi)置函數(shù)判斷通道是否已經(jīng)關(guān)閉,也沒(méi)有可以直接獲取當(dāng)前通道數(shù)量的方法,因此如果對(duì)通道進(jìn)行了錯(cuò)誤的使用,將會(huì)直接引發(fā)系統(tǒng)?panic,這是一件很危險(xiǎn)的事情,下面我們就來(lái)學(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使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Golang中的包及包管理工具go?mod詳解

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

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

    利用Go語(yǔ)言實(shí)現(xiàn)二叉搜索樹(shù)

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

    GO 反射對(duì)性能的影響分析

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

    淺談?dòng)肎o構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法

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

    一文掌握go的sync.RWMutex鎖

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

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

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

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

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

    詳解Go語(yǔ)言中init的使用與常見(jiàn)應(yīng)用場(chǎng)景

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

最新評(píng)論