日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

在微服務(wù)中服務(wù)間依賴(lài)非常常見(jiàn),比如評(píng)論服務(wù)依賴(lài)審核服務(wù)而審核服務(wù)又依賴(lài)反垃圾服務(wù),當(dāng)評(píng)論服務(wù)調(diào)用審核服務(wù)時(shí),審核服務(wù)又調(diào)用反垃圾服務(wù),而這時(shí)反垃圾服務(wù)超時(shí)了,由于審核服務(wù)依賴(lài)反垃圾服務(wù),反垃圾服務(wù)超時(shí)導(dǎo)致審核服務(wù)邏輯一直等待,而這個(gè)時(shí)候評(píng)論服務(wù)又在一直調(diào)用審核服務(wù),審核服務(wù)就有可能因?yàn)槎逊e了大量請(qǐng)求而導(dǎo)致服務(wù)宕機(jī)

熔斷原理與實(shí)現(xiàn)Golang版

由此可見(jiàn),在整個(gè)調(diào)用鏈中,中間的某一個(gè)環(huán)節(jié)出現(xiàn)異常就會(huì)引起上游調(diào)用服務(wù)出現(xiàn)一些列的問(wèn)題,甚至導(dǎo)致整個(gè)調(diào)用鏈的服務(wù)都宕機(jī),這是非常可怕的。因此一個(gè)服務(wù)作為調(diào)用方調(diào)用另一個(gè)服務(wù)時(shí),為了防止被調(diào)用服務(wù)出現(xiàn)問(wèn)題進(jìn)而導(dǎo)致調(diào)用服務(wù)出現(xiàn)問(wèn)題,所以調(diào)用服務(wù)需要進(jìn)行自我保護(hù),而保護(hù)的常用手段就是熔斷

熔斷器原理

熔斷機(jī)制其實(shí)是參考了我們?nèi)粘I钪械谋kU(xiǎn)絲的保護(hù)機(jī)制,當(dāng)電路超負(fù)荷運(yùn)行時(shí),保險(xiǎn)絲會(huì)自動(dòng)的斷開(kāi),從而保證電路中的電器不受損害。而服務(wù)治理中的熔斷機(jī)制,指的是在發(fā)起服務(wù)調(diào)用的時(shí)候,如果被調(diào)用方返回的錯(cuò)誤率超過(guò)一定的閾值,那么后續(xù)的請(qǐng)求將不會(huì)真正發(fā)起請(qǐng)求,而是在調(diào)用方直接返回錯(cuò)誤

在這種模式下,服務(wù)調(diào)用方為每一個(gè)調(diào)用服務(wù)(調(diào)用路徑)維護(hù)一個(gè)狀態(tài)機(jī),在這個(gè)狀態(tài)機(jī)中有三個(gè)狀態(tài):

  • 關(guān)閉(Closed):在這種狀態(tài)下,我們需要一個(gè)計(jì)數(shù)器來(lái)記錄調(diào)用失敗的次數(shù)和總的請(qǐng)求次數(shù),如果在某個(gè)時(shí)間窗口內(nèi),失敗的失敗率達(dá)到預(yù)設(shè)的閾值,則切換到斷開(kāi)狀態(tài),此時(shí)開(kāi)啟一個(gè)超時(shí)時(shí)間,當(dāng)?shù)竭_(dá)該時(shí)間則切換到半關(guān)閉狀態(tài),該超時(shí)時(shí)間是給了系統(tǒng)一次機(jī)會(huì)來(lái)修正導(dǎo)致調(diào)用失敗的錯(cuò)誤,以回到正常的工作狀態(tài)。在關(guān)閉狀態(tài)下,調(diào)用錯(cuò)誤是基于時(shí)間的,在特定的時(shí)間間隔內(nèi)會(huì)重置,這能夠防止偶然錯(cuò)誤導(dǎo)致熔斷器進(jìn)去斷開(kāi)狀態(tài)
  • 打開(kāi)(Open):在該狀態(tài)下,發(fā)起請(qǐng)求時(shí)會(huì)立即返回錯(cuò)誤,一般會(huì)啟動(dòng)一個(gè)超時(shí)計(jì)時(shí)器,當(dāng)計(jì)時(shí)器超時(shí)后,狀態(tài)切換到半打開(kāi)狀態(tài),也可以設(shè)置一個(gè)定時(shí)器,定期的探測(cè)服務(wù)是否恢復(fù)
  • 半打開(kāi)(Half-Open):在該狀態(tài)下,允許應(yīng)用程序一定數(shù)量的請(qǐng)求發(fā)往被調(diào)用服務(wù),如果這些調(diào)用正常,那么可以認(rèn)為被調(diào)用服務(wù)已經(jīng)恢復(fù)正常,此時(shí)熔斷器切換到關(guān)閉狀態(tài),同時(shí)需要重置計(jì)數(shù)。如果這部分仍有調(diào)用失敗的情況,則認(rèn)為被調(diào)用方仍然沒(méi)有恢復(fù),熔斷器會(huì)切換到關(guān)閉狀態(tài),然后重置計(jì)數(shù)器,半打開(kāi)狀態(tài)能夠有效防止正在恢復(fù)中的服務(wù)被突然大量請(qǐng)求再次打垮
熔斷原理與實(shí)現(xiàn)Golang版

服務(wù)治理中引入熔斷機(jī)制,使得系統(tǒng)更加穩(wěn)定和有彈性,在系統(tǒng)從錯(cuò)誤中恢復(fù)的時(shí)候提供穩(wěn)定性,并且減少了錯(cuò)誤對(duì)系統(tǒng)性能的影響,可以快速拒絕可能導(dǎo)致錯(cuò)誤的服務(wù)調(diào)用,而不需要等待真正的錯(cuò)誤返回

熔斷器引入

上面介紹了熔斷器的原理,在了解完原理后,你是否有思考我們?nèi)绾我肴蹟嗥髂兀恳环N方案是在業(yè)務(wù)邏輯中可以加入熔斷器,但顯然是不夠優(yōu)雅也不夠通用的,因此我們需要把熔斷器集成在框架內(nèi),在zRPC框架內(nèi)就內(nèi)置了熔斷器

我們知道,熔斷器主要是用來(lái)保護(hù)調(diào)用端,調(diào)用端在發(fā)起請(qǐng)求的時(shí)候需要先經(jīng)過(guò)熔斷器,而客戶(hù)端攔截器正好兼具了這個(gè)這個(gè)功能,所以在zRPC框架內(nèi)熔斷器是實(shí)現(xiàn)在客戶(hù)端攔截器內(nèi),攔截器的原理如下圖:

熔斷原理與實(shí)現(xiàn)Golang版

對(duì)應(yīng)的代碼為:

func BreakerInterceptor(ctx context.Context, method string, req, reply interface{},
    cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
  // 基于請(qǐng)求方法進(jìn)行熔斷
    breakerName := path.Join(cc.Target(), method)
    return breaker.DoWithAcceptable(breakerName, func() error {
    // 真正發(fā)起調(diào)用
        return invoker(ctx, method, req, reply, cc, opts...)
    // codes.Acceptable判斷哪種錯(cuò)誤需要加入熔斷錯(cuò)誤計(jì)數(shù)
    }, codes.Acceptable)
}

熔斷器實(shí)現(xiàn)

zRPC中熔斷器的實(shí)現(xiàn)參考了Google Sre過(guò)載保護(hù)算法,該算法的原理如下:

  • 請(qǐng)求數(shù)量(requests):調(diào)用方發(fā)起請(qǐng)求的數(shù)量總和
  • 請(qǐng)求接受數(shù)量(accepts):被調(diào)用方正常處理的請(qǐng)求數(shù)量

在正常情況下,這兩個(gè)值是相等的,隨著被調(diào)用方服務(wù)出現(xiàn)異常開(kāi)始拒絕請(qǐng)求,請(qǐng)求接受數(shù)量(accepts)的值開(kāi)始逐漸小于請(qǐng)求數(shù)量(requests),這個(gè)時(shí)候調(diào)用方可以繼續(xù)發(fā)送請(qǐng)求,直到requests = K * accepts,一旦超過(guò)這個(gè)限制,熔斷器就回打開(kāi),新的請(qǐng)求會(huì)在本地以一定的概率被拋棄直接返回錯(cuò)誤,概率的計(jì)算公式如下:

熔斷原理與實(shí)現(xiàn)Golang版

通過(guò)修改算法中的K(倍值),可以調(diào)節(jié)熔斷器的敏感度,當(dāng)降低該倍值會(huì)使自適應(yīng)熔斷算法更敏感,當(dāng)增加該倍值會(huì)使得自適應(yīng)熔斷算法降低敏感度,舉例來(lái)說(shuō),假設(shè)將調(diào)用方的請(qǐng)求上限從 requests = 2 * acceptst 調(diào)整為 requests = 1.1 * accepts 那么就意味著調(diào)用方每十個(gè)請(qǐng)求之中就有一個(gè)請(qǐng)求會(huì)觸發(fā)熔斷

代碼路徑為go-zero/core/breaker

type googleBreaker struct {
    k     float64  // 倍值 默認(rèn)1.5
    stat  *collection.RollingWindow // 滑動(dòng)時(shí)間窗口,用來(lái)對(duì)請(qǐng)求失敗和成功計(jì)數(shù)
    proba *mathx.Proba // 動(dòng)態(tài)概率
}

自適應(yīng)熔斷算法實(shí)現(xiàn)

func (b *googleBreaker) accept() error {
    accepts, total := b.history()  // 請(qǐng)求接受數(shù)量和請(qǐng)求總量
    weightedAccepts := b.k * float64(accepts)
  // 計(jì)算丟棄請(qǐng)求概率
    dropRatio := math.Max(0, (float64(total-protection)-weightedAccepts)/float64(total+1))
    if dropRatio <= 0 {
        return nil
    }
    // 動(dòng)態(tài)判斷是否觸發(fā)熔斷
    if b.proba.TrueOnProba(dropRatio) {
        return ErrServiceUnavailable
    }

    return nil
}

每次發(fā)起請(qǐng)求會(huì)調(diào)用doReq方法,在這個(gè)方法中首先通過(guò)accept效驗(yàn)是否觸發(fā)熔斷,acceptable用來(lái)判斷哪些error會(huì)計(jì)入失敗計(jì)數(shù),定義如下:

func Acceptable(err error) bool {
    switch status.Code(err) {
    case codes.DeadlineExceeded, codes.Internal, codes.Unavailable, codes.DataLoss: // 異常請(qǐng)求錯(cuò)誤
        return false
    default:
        return true
    }
}

如果請(qǐng)求正常則通過(guò)markSuccess把請(qǐng)求數(shù)量和請(qǐng)求接受數(shù)量都加一,如果請(qǐng)求不正常則只有請(qǐng)求數(shù)量會(huì)加一

func (b *googleBreaker) doReq(req func() error, fallback func(err error) error, acceptable Acceptable) error {
    // 判斷是否觸發(fā)熔斷
  if err := b.accept(); err != nil {
        if fallback != nil {
            return fallback(err)
        } else {
            return err
        }
    }

    defer func() {
        if e := recover(); e != nil {
            b.markFailure()
            panic(e)
        }
    }()

  // 執(zhí)行真正的調(diào)用
    err := req()
  // 正常請(qǐng)求計(jì)數(shù)
    if acceptable(err) {
        b.markSuccess()
    } else {
    // 異常請(qǐng)求計(jì)數(shù)
        b.markFailure()
    }

    return err
}

總結(jié)

調(diào)用端可以通過(guò)熔斷機(jī)制進(jìn)行自我保護(hù),防止調(diào)用下游服務(wù)出現(xiàn)異常,或者耗時(shí)過(guò)長(zhǎng)影響調(diào)用端的業(yè)務(wù)邏輯,很多功能完整的微服務(wù)框架都會(huì)內(nèi)置熔斷器。其實(shí),不僅微服務(wù)調(diào)用之間需要熔斷器,在調(diào)用依賴(lài)資源的時(shí)候,比如MySQL、redis等也可以引入熔斷器的機(jī)制。

項(xiàng)目地址:https://github.com/tal-tech/go-zero

分享到:
標(biāo)簽:熔斷
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定