<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「GoCN酷Go推薦」重試工具 — retry-go

          共 2198字,需瀏覽 5分鐘

           ·

          2021-10-17 11:19

          簡(jiǎn)介

          在微服務(wù)架構(gòu)中,通常會(huì)有很多的小服務(wù),小服務(wù)之間存在大量 RPC 調(diào)用,但時(shí)常因?yàn)榫W(wǎng)絡(luò)抖動(dòng)等原因,造成請(qǐng)求失敗,這時(shí)候使用重試機(jī)制可以提高請(qǐng)求的最終成功率,減少故障影響,讓系統(tǒng)運(yùn)行更穩(wěn)定。retry-go 是一個(gè)功能比較完善的 golang 重試庫(kù)。

          如何使用

          retry-go的使用非常簡(jiǎn)單,直接使用 Do方法即可。如下是一個(gè)發(fā)起 HTTP Get 請(qǐng)求的重試示例 :

          url?:=?"https://gocn.vip"
          var?body?[]byte

          err?:=?retry.Do(
          ?func()?error?{
          ??resp,?err?:=?http.Get(url)
          ??if?err?!=?nil?{
          ???return?err
          ??}
          ??defer?resp.Body.Close()
          ??body,?err?=?ioutil.ReadAll(resp.Body)
          ??if?err?!=?nil?{
          ???return?err
          ??}

          ??return?nil
          ?},
          )

          fmt.Println(body)

          調(diào)用時(shí),有一些可選的配置項(xiàng):

          • attempts 最大重試次數(shù)
          • delay 重試延遲時(shí)間
          • maxDelay 最大重試延遲時(shí)間,選擇指數(shù)退避策略時(shí),該配置會(huì)限制等待時(shí)間上限
          • maxJitter 隨機(jī)退避策略的最大等待時(shí)間
          • onRetry 每次重試時(shí)進(jìn)行的一次回調(diào)
          • retryIf 重試時(shí)的一個(gè)條件判斷
          • delayType 退避策略類型
          • lastErrorOnly 是否只返回上次重試的錯(cuò)誤

          BackOff 退避策略

          對(duì)于一些暫時(shí)性的錯(cuò)誤,如網(wǎng)絡(luò)抖動(dòng)等,立即重試可能還是會(huì)失敗,通常等待一小會(huì)兒再重試的話成功率會(huì)較高,并且這種策略也可以打散上游重試的時(shí)間,避免同時(shí)重試而導(dǎo)致的瞬間流量高峰。決定等待多久之后再重試的方法叫做退避策略。retry-go 實(shí)現(xiàn)了以下幾個(gè)退避策略:

          func BackOffDelay

          func?BackOffDelay(n?uint,?_?error,?config?*Config)?time.Duration

          BackOffDelay 提供一個(gè)指數(shù)避退策略,連續(xù)重試時(shí),每次等待時(shí)間都是前一次的 2 倍。

          func FixedDelay

          func?FixedDelay(_?uint,?_?error,?config?*Config)?time.Duration

          FixedDelay 在每次重試時(shí),等待一個(gè)固定延遲時(shí)間。

          func RandomDelay

          func?RandomDelay(_?uint,?_?error,?config?*Config)?time.Duration

          RandomDelay 在 0 - config.maxJitter 內(nèi)隨機(jī)等待一個(gè)時(shí)間后重試。

          func CombineDelay

          func?CombineDelay(delays?...DelayTypeFunc)?DelayTypeFunc

          CombineDelay ?提供結(jié)合多種策略實(shí)現(xiàn)一個(gè)新策略的能力。

          retry-go默認(rèn)的退避策略為 ?BackOffDelayRandomDelay結(jié)合的方式,即在指數(shù)遞增的同時(shí),加一個(gè)隨機(jī)時(shí)間。

          自定義的延時(shí)策略

          下面是一個(gè)官方給出的例子,當(dāng)請(qǐng)求的響應(yīng)有Retry-After頭時(shí),使用該值去進(jìn)行等待,其他情況按照BackOffDelay策略進(jìn)行延時(shí)等待。

          var?_?error?=?(*RetriableError)(nil)

          func?test2(){
          ?var?body?[]byte

          ?err?:=?retry.Do(
          ??func()?error?{
          ???resp,?err?:=?http.Get("URL")

          ???if?err?==?nil?{
          ????defer?func()?{
          ?????if?err?:=?resp.Body.Close();?err?!=?nil?{
          ??????panic(err)
          ?????}
          ????}()
          ????body,?err?=?ioutil.ReadAll(resp.Body)
          ????if?resp.StatusCode?!=?200?{
          ?????err?=?fmt.Errorf("HTTP?%d:?%s",?resp.StatusCode,?string(body))
          ?????if?resp.StatusCode?==?http.StatusTooManyRequests?{
          ??????//?check?Retry-After?header?if?it?contains?seconds?to?wait?for?the?next?retry
          ??????if?retryAfter,?e?:=?strconv.ParseInt(resp.Header.Get("Retry-After"),?10,?32);?e?==?nil?{
          ???????//?the?server?returns?0?to?inform?that?the?operation?cannot?be?retried
          ???????if?retryAfter?<=?0?{
          ????????return?retry.Unrecoverable(err)
          ???????}
          ???????return?&RetriableError{
          ????????Err:????????err,
          ????????RetryAfter:?time.Duration(retryAfter)?*?time.Second,
          ???????}
          ??????}
          ??????//?A?real?implementation?should?also?try?to?http.Parse?the?retryAfter?response?header
          ??????//?to?conform?with?HTTP?specification.?Herein?we?know?here?that?we?return?only?seconds.
          ?????}
          ????}
          ???}

          ???return?err
          ??},
          ??retry.DelayType(func(n?uint,?err?error,?config?*retry.Config)?time.Duration?{
          ???fmt.Println("Server?fails?with:?"?+?err.Error())
          ???if?retriable,?ok?:=?err.(*RetriableError);?ok?{
          ????fmt.Printf("Client?follows?server?recommendation?to?retry?after?%v\n",?retriable.RetryAfter)
          ????return?retriable.RetryAfter
          ???}
          ???//?apply?a?default?exponential?back?off?strategy
          ???return?retry.BackOffDelay(n,?err,?config)
          ??}),
          ?)

          ?fmt.Println("Server?responds?with:?"?+?string(body))
          }

          總結(jié)

          重試可以提升服務(wù)調(diào)用的成功率,但重試時(shí)也要警惕由此帶來(lái)的放大故障的風(fēng)險(xiǎn)。選擇合適的退避策略,控制放大效應(yīng),才能優(yōu)雅的提升服務(wù)的穩(wěn)定性。

          Reference

          如何優(yōu)雅地重試-InfoQ

          [譯] 重試、超時(shí)和退避 | nettee 的 blog


          《酷Go推薦》招募:


          各位Gopher同學(xué),最近我們社區(qū)打算推出一個(gè)類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個(gè)庫(kù)或者好的項(xiàng)目,然后寫一點(diǎn)這個(gè)庫(kù)使用方法或者優(yōu)點(diǎn)之類的,這樣可以真正的幫助到大家能夠?qū)W習(xí)到

          新的庫(kù),并且知道怎么用。


          大概規(guī)則和每日新聞?lì)愃疲绻麍?bào)名人多的話每個(gè)人一個(gè)月輪到一次,歡迎大家報(bào)名!戳「閱讀原文」,即可報(bào)名


          掃碼也可以加入 GoCN 的大家族喲~


          瀏覽 121
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久婷婷夜色精品国产冻传媒 | 毛片4级中文字幕无码 | 玖玖在线| 亚洲电影第二页 | 婷婷国产夫妻 |