亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang熔斷器如何實現

發布時間:2022-01-10 10:47:25 來源:億速云 閱讀:155 作者:iii 欄目:開發技術

這篇“golang熔斷器如何實現”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“golang熔斷器如何實現”文章吧。

熔斷器像是一個保險絲。當我們依賴的服務出現問題時,可以及時容錯。一方面可以減少依賴服務對自身訪問的依賴,防止出現雪崩效應;另一方面降低請求頻率以方便上游盡快恢復服務。

熔斷器的應用也非常廣泛。除了在我們應用中,為了請求服務時使用熔斷器外,在 web 網關、微服務中,也有非常廣泛的應用。

1.熔斷器的模式

gobreaker 是基于《微軟云設計模式》一書中的熔斷器模式的 Golang 實現。有 sony 公司開源,目前 star 數有 1.2K。使用人數較多。

下面是模式定義的一個狀態機:

golang熔斷器如何實現

熔斷器有三種狀態,四種狀態轉移的情況:

  • 熔斷器關閉狀態,服務正常訪問

  • 熔斷器開啟狀態,服務異常

  • 熔斷器半開狀態,部分請求限流訪問

四種狀態轉移:

  • 在熔斷器關閉狀態下,當失敗后并滿足一定條件后,將直接轉移為熔斷器開啟狀態。

  • 在熔斷器開啟狀態下,如果過了規定的時間,將進入半開啟狀態,驗證目前服務是否可用。

  • 在熔斷器半開啟狀態下,如果出現失敗,則再次進入關閉狀態。

  • 在熔斷器半開啟后,所有請求(有限額)都是成功的,則熔斷器關閉。所有請求將正常訪問。

2.gobreaker 的實現

gobreaker 是在上述狀態機的基礎上,實現的一個熔斷器。

2.1熔斷器的定義

type CircuitBreaker struct {  
  name          string  
  maxRequests   uint32  // 最大請求數 (半開啟狀態會限流)  
  interval      time.Duration   // 統計周期  
  timeout       time.Duration   // 進入熔斷后的超時時間  
  readyToTrip   func(counts Counts) bool // 通過 Counts 判斷是否開啟熔斷。需要自定義  
  onStateChange func(name string, from State, to State) // 狀態修改時的鉤子函數  

  mutex      sync.Mutex // 互斥鎖,下面數據的更新都需要加鎖  
  state      State  // 記錄了當前的狀態  
  generation uint64 // 標記屬于哪個周期  
  counts     Counts // 計數器,統計了 成功、失敗、連續成功、連續失敗等,用于決策是否進入熔斷  
  expiry     time.Time // 進入下個周期的時間  
}

其中,如下參數是我們可以自定義的:

  • MaxRequests:最大請求數。當在最大請求數下,均請求正常的情況下,會關閉熔斷器

  • interval:一個正常的統計周期。如果為 0,那每次都會將計數清零

  • timeout: 進入熔斷后,可以再次請求的時間

  • readyToTrip:判斷熔斷生效的鉤子函數

  • onStateChagne:狀態變更的鉤子函數

2.2請求的執行

熔斷器的執行操作,主要包括三個階段;①請求之前的判定;②服務的請求執行;③請求后的狀態和計數的更新

// 熔斷器的調用  
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 {  
      // ③ panic 的捕獲  
      cb.afterRequest(generation, false)  
      panic(e)  
    }  
  }()  

  // ② 請求和執行  
  result, err := req()  

  // ③ 更新計數  
  cb.afterRequest(generation, err == nil)  
  return result, err  
}

2.3請求之前的判定操作

請求之前,會判斷當前熔斷器的狀態。如果熔斷器以開啟,則不會繼續請求。如果熔斷器半開,并且已達到最大請求閾值,也不會繼續請求。

func (cb *CircuitBreaker) beforeRequest() (uint64, error) {  
  cb.mutex.Lock()  
  defer cb.mutex.Unlock()  

  now := time.Now()  
  state, generation := cb.currentState(now)  

  if state == StateOpen { // 熔斷器開啟,直接返回  
    return generation, ErrOpenState  
  } else if state == StateHalfOpen && cb.counts.Requests >= cb.maxRequests { // 如果是半打開的狀態,并且請求次數過多了,則直接返回  
    return generation, ErrTooManyRequests  
  }  

  cb.counts.onRequest()  
  return generation, nil  
}

其中當前狀態的計算,是依據當前狀態來的。如果當前狀態為已開啟,則判斷是否已經超時,超時就可以變更狀態到半開;如果當前狀態為關閉狀態,則通過周期判斷是否進入下一個周期。

func (cb *CircuitBreaker) currentState(now time.Time) (State, uint64) {  
  switch cb.state {  
  case StateClosed:  
    if !cb.expiry.IsZero() && cb.expiry.Before(now) { // 是否需要進入下一個計數周期  
      cb.toNewGeneration(now)  
    }  
  case StateOpen:  
    if cb.expiry.Before(now) {  
      // 熔斷器由開啟變更為半開  
      cb.setState(StateHalfOpen, now)  
    }  
  }  
  return cb.state, cb.generation  
}

周期長度的設定,也是以據當前狀態來的。如果當前正常(熔斷器關閉),則設置為一個 interval 的周期;如果當前熔斷器是開啟狀態,則設置為超時時間(超時后,才能變更為半開狀態)。

2.4請求之后的處理操作

每次請求之后,會通過請求結果是否成功,對熔斷器做計數。

func (cb *CircuitBreaker) afterRequest(before uint64, success bool) {  
  cb.mutex.Lock()  
  defer cb.mutex.Unlock()  

  now := time.Now()  

  // 如果不在一個周期,就不再計數  
  state, generation := cb.currentState(now)  
  if generation != before {  
    return  
  }  

  if success {  
    cb.onSuccess(state, now)  
  } else {  
    cb.onFailure(state, now)  
  }  
}

如果在半開的狀態下:

如果請求成功,則會判斷當前連續成功的請求數 大于等于 maxRequests, 則可以把狀態由半開狀態轉移為關閉狀態
如果在半開狀態下,請求失敗,則會直接將半開狀態轉移為開啟狀態
如果在關閉狀態下:

如果請求成功,則計數更新
如果請求失敗,則調用 readyToTrip 判斷是否需要將狀態關閉狀態轉移為開啟狀態

以上就是關于“golang熔斷器如何實現”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

济源市| 黔东| 旬阳县| 韩城市| 虹口区| 淅川县| 马龙县| 富平县| 城固县| 防城港市| 云林县| 兴海县| 商城县| 伊宁市| 津市市| 绥中县| 通江县| 香河县| 沙坪坝区| 叶城县| 射阳县| 桂平市| 交城县| 寻乌县| 绥宁县| 神木县| 壤塘县| 新蔡县| 九寨沟县| 女性| 吴忠市| 枞阳县| 左权县| 布尔津县| 得荣县| 潮州市| 侯马市| 英吉沙县| 永川市| 江阴市| 太白县|