Kitex 請求重試

2022-04-26 14:48 更新

1. 重試功能說明

目前有三類重試:超時重試、Backup Request,建連失敗重試(默認)。其中建連失敗是網(wǎng)絡層面問題,由于請求未發(fā)出,框架會默認重試。 本文檔介紹前兩類重試的使用:

  • 超時重試:提高服務整體的成功率
  • Backup Request:減少服務的延遲波動

因為很多的業(yè)務請求不具有冪等性,這兩類重試不會作為默認策略。

1.1 注意: 

  • 確認你的服務具有冪等性,再開啟重試
  • 超時重試會增加延遲

2. 重試策略

超時重試和 Backup Request 策略只能配置其中之一。

  • 超時重試
配置項 默認值 說明 限制
MaxRetryTimes 2 最大重試次數(shù),不包含首次請求。如果配置為 0 表示停止重試。 合法值:[0-5]
MaxDurationMS 0 累計最大耗時,包括首次失敗請求和重試請求耗時,如果耗時達到了限制的時間則停止后續(xù)的重試。0 表示無限制。注意:如果配置,該配置項必須大于請求超時時間。
EERThreshold 10% 重試熔斷錯誤率閾值, 方法級別請求錯誤率超過閾值則停止重試。 合法值:(0-30%]
ChainStop - 鏈路中止, 默認啟用。如果上游請求是重試請求,超時后不會重試。 >= v0.0.5 后作為默認策略
DDLStop false 鏈路超時中止,該策略是從鏈路的超時時間判斷是否需要重試。注意,Kitex 未內(nèi)置該實現(xiàn),需通過 retry.RegisterDDLStop(ddlStopFunc) 注冊 DDL func,結(jié)合鏈路超時判斷,實現(xiàn)上建議基于上游的發(fā)起調(diào)用的時間戳和超時時間判斷。??
BackOff None 重試等待策略,默認立即重試(NoneBackOff)??蛇x:固定時長退避 (FixedBackOff)、隨機時長退避 (RandomBackOff)。
RetrySameNode false 框架默認選擇其他節(jié)點重試,若需要同節(jié)點重試,可配置為 true。
  • Backup Request
配置項 默認值 說明 限制
RetryDelayMS - Backup Request 的等待時間,若該時間內(nèi)若請求未返回,會發(fā)送新的請求。必須手動配置,建議參考 TP99。
MaxRetryTimes 1 最大重試次數(shù),不包含首次請求。 如果配置為 0 表示停止重試。 合法值:[0-2]
EERThreshold 10% 重試熔斷錯誤率閾值,方法級別請求錯誤率超過閾值則停止重試。 合法值:(0-30%]
ChainStop - 鏈路中止, 默認啟用。如果上游請求是重試請求,不會發(fā)送 Backup Request。 >= v0.0.5 后作為默認策略
RetrySameNode false 框架默認選擇其他節(jié)點重試,若需要同節(jié)點重試,可配置為 true

3. 使用方式

3.1 代碼配置開啟 

注意:若通過代碼配置開啟重試,動態(tài)配置 (見 3.3) 則無法生效。

3.1.1 超時重試配置

  • 配置示例:

// import "github.com/cloudwego/kitex/pkg/retry"
fp := retry.NewFailurePolicy()
fp.WithMaxRetryTimes(3) // 配置最多重試3次
xxxCli := xxxservice.NewClient("destServiceName", client.WithFailureRetry(fp))

  • 策略選擇:

fp := retry.NewFailurePolicy()

// 重試次數(shù), 默認2,不包含首次請求
fp.WithMaxRetryTimes(xxx)

// 總耗時,包括首次失敗請求和重試請求耗時達到了限制的duration,則停止后續(xù)的重試。
fp.WithMaxDurationMS(xxx)

// 關閉鏈路中止
fp.DisableChainRetryStop()

// 開啟DDL中止
fp.WithDDLStop()

// 退避策略,默認無退避策略
fp.WithFixedBackOff(fixMS int) // 固定時長退避
fp.WithRandomBackOff(minMS int, maxMS int) // 隨機時長退避

// 開啟重試熔斷
fp.WithRetryBreaker(errRate float64)

// 同一節(jié)點重試
fp.WithRetrySameNode()

3.1.2 Backup Request 配置

  • Retry Delay 建議

建議配置為 TP99,則 1% 請求會觸發(fā) Backup Request。

  • 配置示例:

// 首次請求 xxx ms未返回,發(fā)起 backup 請求,并開啟鏈路中止
bp := retry.NewBackupPolicy(xxx)
xxxCli := xxxservice.NewClient("destServiceName", client.WithBackupRequest(bp))

  • 策略選擇:

bp := retry.NewBackupPolicy(xxx)

// 重試次數(shù), 默認1,不包含首次請求
bp.WithMaxRetryTimes(xxx)

// 關閉鏈路中止
bp.DisableChainRetryStop()

// 開啟重試熔斷
bp.WithRetryBreaker(errRate float64)

// 同一節(jié)點重試
bp.WithRetrySameNode()

3.2 復用熔斷器

當開啟了服務的熔斷配置可以復用熔斷的統(tǒng)計減少額外的 CPU 消耗,注意重試的熔斷閾值須低于服務的熔斷閾值,使用如下:

// 1. 初始化 kitex 內(nèi)置的 cbsuite
cbs := circuitbreak.NewCBSuite(circuitbreak.RPCInfo2Key)
// 2. 初始化 retryContainer,傳入ServiceControl和ServicePanel
retryC := retry.NewRetryContainerWithCB(cs.cbs.ServiceControl(), cs.cbs.ServicePanel())

var opts []client.Option
// 3. 配置 retryContainer
opts = append(opts, client.WithRetryContainer(retryC))
// 4. 配置 Service circuit breaker
opts = append(opts, client.WithMiddleware(cbs.ServiceCBMW()))

// 5. 初始化 Client, 傳入配置 option
cli, err := xxxservice.NewClient(targetService, opts...)

3.3 動態(tài)開啟或調(diào)整策略

若需要結(jié)合遠程配置,動態(tài)開啟重試或運行時調(diào)整策略,可以通過 retryContainer 的 NotifyPolicyChange 方法生效,目前 Kitex 開源版本暫未提供遠程配置模塊,使用者可集成自己的配置中心。注意:若已通過代碼配置開啟,動態(tài)配置則無法生效。 使用示例:

retryC := retry.NewRetryContainer()
// demo
// 1. define your change func
// 2. exec yourChangeFunc in your config module
yourChangeFunc := func(key string, oldData, newData interface{}) {
    newConf := newData.(*retry.Policy)
    method := parseMethod(key)
    retryC.NotifyPolicyChange(method, policy)
}


// configure retryContainer
cli, err := xxxservice.NewClient(targetService, client.WithRetryContainer(retryC))

4. 監(jiān)控埋點 

Kitex 對重試的請求在 rpcinfo 中記錄了重試次數(shù)和之前請求的耗時,可以在Client側(cè)的 metric 或日志中根據(jù) retry tag 區(qū)分上報或輸出。獲取方式:

var retryCount string
var lastCosts string

toInfo := rpcinfo.GetRPCInfo(ctx).To()
if retryTag, ok := toInfo.Tag(rpcinfo.RetryTag); ok {
   retryCount = retryTag
   if lastCostTag, ok := toInfo.Tag(rpcinfo.RetryLastCostTag); ok {
      lastCosts = lastCostTag
   }
}

5. 下游識別重試請求 

如果使用 TTHeader 作為傳輸協(xié)議,下游 handler 可以通過如下方式判斷當前是否是重試請求,自行決定是否繼續(xù)處理。

retryReqCount, exist := metainfo.GetPersistentValue(ctx,retry.TransitKey)

比如 retryReqCount = 2,表示第二次重試請求(不包括首次請求),則采取業(yè)務降級策略返回部分或 mock 數(shù)據(jù)返回(非重試請求沒有該信息)。

Q: 框架默認開啟鏈路中止,業(yè)務是否還有必要識別重試請求?
鏈路中止是指鏈路上的重試請求不會重試,比如 A->B->C,A 向 B 發(fā)送的是重試請求,如果 B->C 超時了或者配置了 Backup,則 B 不會再發(fā)送重試請求到 C。如果業(yè)務自行識別重試請求,可以直接決定是否繼續(xù)請求到 C。簡言之鏈路中止避免了 B 向 C 發(fā)送重試請求導致重試放大,業(yè)務自己控制可以完全避免 B 到 C 的請求。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號