Sony gobreaker容斷器源碼分析

最近看了一下go-kit久锥,發(fā)現(xiàn)這個(gè)微服務(wù)框架的容斷器瑟由,也是使用sony開源的作為基礎(chǔ)冤寿。

[sony開源在 github 的容斷器](https://github.com/sony/gobreaker)

在源代頭注釋中發(fā)現(xiàn),原來sony實(shí)現(xiàn)的是微軟2015時(shí)公布的CircuitBreaker標(biāo)準(zhǔn)督怜,果然微軟才開源界的大神。

## 1)微軟定義的 Circuit breaker

我不知道正確怎么翻譯,直觀翻譯究流,可能叫:環(huán)形容斷器(或叫:循環(huán)狀態(tài)自動(dòng)切換容斷器)动遭。

因?yàn)樗窃谙旅?個(gè)狀態(tài)循環(huán)切換? :

```

? ? ? ? Closed

? ? ? ? /? ? \

Half-Open <--> Open

初始狀態(tài)是:Closed,指容斷器放行所有請求偷仿。

達(dá)到一定數(shù)量的錯(cuò)誤計(jì)數(shù),進(jìn)入Open 狀態(tài)酝静,指容斷發(fā)生,下游出現(xiàn)錯(cuò)誤宗苍,不能再放行請求薄榛。

經(jīng)過一段Interval時(shí)間后,自動(dòng)進(jìn)入Half-Open狀態(tài)丽啡,然后開始嘗試對成功請求計(jì)數(shù)硬猫。

進(jìn)入Half-Open后,根據(jù)成功/失敗計(jì)數(shù)情況馏予,會自動(dòng)進(jìn)入Closed或Open盔性。

```

## 2)sony開源的go實(shí)現(xiàn)

```go

// 從定義的錯(cuò)誤來看,sony的應(yīng)該增加了對連接數(shù)進(jìn)行了限制 蛹尝。

var (

? ? // ErrTooManyRequests is returned when the CB state is half open and the requests count is over the cb maxRequests

? ? ErrTooManyRequests = errors.New("too many requests")

? ? // ErrOpenState is returned when the CB state is open

? ? ErrOpenState = errors.New("circuit breaker is open")

)

```

### 2.1) 通過Settings的實(shí)現(xiàn)悉尾,了解可配置功能:

```go

type Settings struct {

? ? Name? ? ? ? ? string

? ? MaxRequests? uint32? ? ? ? // 半開狀態(tài)期最大允許放行請求:即進(jìn)入Half-Open狀態(tài)時(shí),一個(gè)時(shí)間周期內(nèi)允許最大同時(shí)請求數(shù)(如果還達(dá)不到切回closed狀態(tài)條件愕难,則不能再放行請求)惫霸。

? ? Interval? ? ? time.Duration // closed狀態(tài)時(shí),重置計(jì)數(shù)的時(shí)間周期猜丹;如果配為0硅卢,切入Open后永不切回Closed--有點(diǎn)暴力藏杖。

? ? Timeout? ? ? time.Duration // 進(jìn)入Open狀態(tài)后脉顿,多長時(shí)間會自動(dòng)切成 Half-open,默認(rèn)60s祥楣,不能配為0汉柒。

? ? // ReadyToTrip回調(diào)函數(shù):進(jìn)入Open狀態(tài)的條件,比如默認(rèn)是連接5次出錯(cuò)兽间,即進(jìn)入Open狀態(tài)正塌,即可對容斷條件進(jìn)行配置。在fail計(jì)數(shù)發(fā)生后乓诽,回調(diào)一次鸠天。

? ? ReadyToTrip? func(counts Counts) bool

? ? // 狀態(tài)切換時(shí)的容斷器

? ? OnStateChange func(name string, from State, to State)

}

```

### 2.2)核心的*執(zhí)行函數(shù)*實(shí)現(xiàn)

```go

func (cb *CircuitBreaker) Execute(req func() (interface{}, error)) (interface{}, error) {

? ? generation, err := cb.beforeRequest() //

? ? if err != nil {

? ? ? ? return nil, err

? ? }

? ? defer func() {

? ? ? ? e := recover()

? ? ? ? if e != nil {

? ? ? ? ? ? cb.afterRequest(generation, false)

? ? ? ? ? ? panic(e) // 如果代碼發(fā)生了panic,繼續(xù)panic給上層調(diào)用者去recover奶段。

? ? ? ? }

? ? }()

? ? result, err := req()

? ? cb.afterRequest(generation, err == nil)

? ? return result, err

}

```

### 2.2 關(guān)鍵? func beforeRequest()

函數(shù)做了幾件事:

0. 函數(shù)的核心功能:判斷是否放行請求剥纷,計(jì)數(shù)或達(dá)到切換新條件剛切換。

1. 判斷是否Closed蹲缠,如是悠垛,放行所有請求。

? ? ? - 并且判斷時(shí)間是否達(dá)到Interval周期,從而清空計(jì)數(shù)因俐,進(jìn)入新周期周偎,調(diào)用toNewGeneration()

2. 如果是Open狀態(tài)撑帖,返回ErrOpenState胡嘿,---不放行所有請求。

? ? ? - 同樣判斷周期時(shí)間衷敌,到達(dá)則 同樣調(diào)用 toNewGeneration(){清空計(jì)數(shù)}

3. 如果是half-open狀態(tài)缴罗,則判斷是否已放行MaxRequests個(gè)請求,如未達(dá)到剛放行面氓;否則返回:ErrTooManyRequests。

4. 此函數(shù)一旦放行請求掘譬,就會對請求計(jì)數(shù)加1(conut.onRequest())呻拌,請求后到另一個(gè)關(guān)鍵函數(shù) : afterRequest()。

### 2.3 關(guān)鍵? func afterRequest()

1. 函數(shù)核心內(nèi)容很簡單酿箭,就對成功/失敗進(jìn)行計(jì)數(shù)趾娃,達(dá)到條件則切換狀態(tài)。

2. 與beforeRequest一樣妇蛀,會調(diào)用公共函數(shù) currentState(now)

? ? ? - currentState(now) 先判斷是否進(jìn)入一個(gè)先的計(jì)數(shù)時(shí)間周期(Interval), 是則重置計(jì)數(shù)笤成,改變?nèi)輸嗥鳡顟B(tài),并返回新一代纵诞。

? ? ? - 如果request耗時(shí)大于Interval, 幾本每次都會進(jìn)入新的計(jì)數(shù)周期培遵,容斷器就沒什么意義了登刺。

## 代碼的核心內(nèi)容

1. 使用了一個(gè)generation的概念嗡呼,每一個(gè)時(shí)間周期(Interval)的計(jì)數(shù)(count)狀態(tài)稱為一個(gè)generation。

2. 在before/after的兩個(gè)函數(shù)中揍很,實(shí)現(xiàn)了兩個(gè)狀態(tài)自動(dòng)切換的機(jī)制:

? ? - 在同一個(gè)generation(即時(shí)間)周期內(nèi)万伤,計(jì)數(shù)滿足狀態(tài)切換條件,即自動(dòng)切換蛉迹;

? ? - 超過一個(gè)generation時(shí)間周期的也會自動(dòng)切換放妈;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芜抒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宅倒,更是在濱河造成了極大的恐慌,老刑警劉巖蹭劈,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铺韧,死亡現(xiàn)場離奇詭異缓淹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)料仗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門伏蚊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人氛改,你說我怎么就攤上這事。” “怎么了凳怨?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵肤舞,是天一觀的道長。 經(jīng)常有香客問我芒率,道長篙顺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任匪蟀,我火速辦了婚禮宰僧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘段化。我一直安慰自己造成,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布佃延。 她就那樣靜靜地躺著夷磕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尺棋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天成福,我揣著相機(jī)與錄音荆残,去河邊找鬼内斯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俘闯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播此疹,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蝗碎,長吁一口氣:“原來是場噩夢啊……” “哼旗扑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肩豁,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤清钥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后祟昭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體篡悟,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了急凰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疾忍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出一罩,到底是詐尸還是另有隱情杨幼,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布聂渊,位于F島的核電站推汽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏歧沪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一莲组、第九天 我趴在偏房一處隱蔽的房頂上張望诊胞。 院中可真熱鬧,春花似錦锹杈、人聲如沸撵孤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至咬清,卻和暖如春闭专,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旧烧。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工影钉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掘剪。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓平委,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夺谁。 傳聞我的和親對象是個(gè)殘疾皇子廉赔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容