IResponse约束增加NeedRetry是否需要重试方法

This commit is contained in:
白茶清欢 2025-05-07 16:32:20 +08:00
parent 741c9c8ea0
commit b335d7c2bb
3 changed files with 45 additions and 30 deletions

View File

@ -27,4 +27,6 @@ type IResponse interface {
BusinessSuccess(reqCfg *define.Request, response *define.Response) bool BusinessSuccess(reqCfg *define.Request, response *define.Response) bool
// HttpSuccess http状态码是否成功 // HttpSuccess http状态码是否成功
HttpSuccess(reqCfg *define.Request, response *define.Response) bool HttpSuccess(reqCfg *define.Request, response *define.Response) bool
// NeedRetry 是否需要重试
NeedRetry(reqCfg *define.Request, response *define.Response) bool
} }

View File

@ -345,38 +345,22 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
err error err error
) )
response := hc.newResponse() var response *define.Response
// +1 是因为正常便会请求一次, 正常请求1次 + 重试次数 = 请求总次数
for i := 0; i < hc.reqCfg.RetryRule.RetryCount+1; i++ { for i := 0; i < hc.reqCfg.RetryRule.RetryCount+1; i++ {
if i > 0 { if i > 0 && nil != response {
// 非首次请求, 说明是重试, 暂停指定时间间隔
time.Sleep(time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond)
}
if response.Seq > 0 {
// 说明是重试, 记录上一次的请求信息 // 说明是重试, 记录上一次的请求信息
response.RequestFinishTime = time.Now().UnixMilli() response.RequestFinishTime = time.Now().UnixMilli()
response.UsedTime = response.RequestFinishTime - response.RequestStartTime response.UsedTime = response.RequestFinishTime - response.RequestStartTime
for _, itemAfterResponse := range hc.requestFinishHandler { for _, itemAfterResponse := range hc.requestFinishHandler {
itemAfterResponse(hc.reqCfg, response) itemAfterResponse(hc.reqCfg, response)
} }
// 非首次请求, 说明是重试, 暂停指定时间间隔
time.Sleep(time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond)
} }
response.RequestStartTime = time.Now().UnixMilli() // 每次重置请求时间 response = hc.newResponse()
response.RequestFinishTime = 0 // 清空完成时间 response.Seq = i
response.Seq++ response.RequestCount = i + 1
response.RequestCount++
retryHttpCodeTable := make(map[int64]bool)
retryBusinessCodeTable := make(map[string]bool)
if nil != hc.reqCfg.RetryRule {
for _, httpCode := range hc.reqCfg.RetryRule.RetryHttpCodeList {
retryHttpCodeTable[httpCode] = true
}
for _, businessCode := range hc.reqCfg.RetryRule.RetryBusinessCodeList {
retryBusinessCodeTable[businessCode] = true
}
}
successHttpCodeTable := make(map[int]bool)
for _, itemHttpCode := range hc.reqCfg.SuccessHttpCodeList {
successHttpCodeTable[itemHttpCode] = true
}
if response.RestyResponse, err = hc.request.Send(); nil != err { if response.RestyResponse, err = hc.request.Send(); nil != err {
errType := define.RequestFailTypeSend errType := define.RequestFailTypeSend
if err.Error() == resty.ErrRateLimitExceeded.Error() { if err.Error() == resty.ErrRateLimitExceeded.Error() {
@ -386,6 +370,9 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
if netErr.Timeout() { if netErr.Timeout() {
// 请求超时 // 请求超时
errType = define.RequestFailTypeTimeoutError errType = define.RequestFailTypeTimeoutError
// 重置响应状态码
response.HttpCode = 499
response.HttpCodeStatus = "request timeout"
} }
} }
response.FailInfo = &define.ResponseFailInfo{ response.FailInfo = &define.ResponseFailInfo{
@ -402,7 +389,7 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
break break
} }
if errType == define.RequestFailTypeTimeoutError && !retryHttpCodeTable[499] { if errType == define.RequestFailTypeTimeoutError && !hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response) {
// 未配置超时重试 // 未配置超时重试
log.RecordDebug("请求超时, 未配置超时重试, 不进行重试", nil, hc.reqCfg) log.RecordDebug("请求超时, 未配置超时重试, 不进行重试", nil, hc.reqCfg)
break break
@ -441,15 +428,16 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
Type: errType, Type: errType,
Message: "http code is " + response.HttpCodeStatus + ", not success", Message: "http code is " + response.HttpCodeStatus + ", not success",
} }
needRetry := hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response)
log.RecordWarn("请求响应的http状态码非成功", map[string]any{ log.RecordWarn("请求响应的http状态码非成功", map[string]any{
"err_type": errType, "err_type": errType,
"err_msg": response.RestyResponse.Status(), "err_msg": response.RestyResponse.Status(),
"response_http_code": response.HttpCode, "response_http_code": response.HttpCode,
"success_http_code": hc.reqCfg.SuccessHttpCodeList, "success_http_code": hc.reqCfg.SuccessHttpCodeList,
"allow_retry": len(retryHttpCodeTable) == 0 || retryHttpCodeTable[int64(response.HttpCode)], "allow_retry": needRetry,
"time_interval": time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond, "time_interval": time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond,
}, hc.reqCfg) }, hc.reqCfg)
if len(retryHttpCodeTable) > 0 && !retryHttpCodeTable[int64(response.HttpCode)] { if !needRetry {
// 未配置http code重试 // 未配置http code重试
break break
} }
@ -460,15 +448,17 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
Type: define.RequestFailTypeBusinessError, Type: define.RequestFailTypeBusinessError,
Message: "business code is " + response.Code + ", not success", Message: "business code is " + response.Code + ", not success",
} }
needRetry := hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response)
log.RecordWarn("请求响应状态码成功, 业务状态码非成功", map[string]any{ log.RecordWarn("请求响应状态码成功, 业务状态码非成功", map[string]any{
"err_type": response.FailInfo.Type, "err_type": response.FailInfo.Type,
"err_msg": response.Message, "err_msg": response.Message,
"response_code": response.Code, "response_code": response.Code,
"success_code": hc.reqCfg.SuccessCodeList, "success_code": hc.reqCfg.SuccessCodeList,
"allow_retry": len(retryBusinessCodeTable) == 0 || retryBusinessCodeTable[response.Code], "allow_retry": needRetry,
"time_interval": time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond, "time_interval": time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond,
}, hc.reqCfg) }, hc.reqCfg)
if len(retryBusinessCodeTable) > 0 && !retryBusinessCodeTable[response.Code] { if needRetry {
// 未配置业务code重试 // 未配置业务code重试
break break
} }
@ -504,7 +494,7 @@ func (hc *HttpClient) newResponse() *define.Response {
HttpCodeStatus: "", HttpCodeStatus: "",
ResponseDataRule: nil, ResponseDataRule: nil,
Seq: 0, Seq: 0,
RequestStartTime: 0, RequestStartTime: time.Now().UnixMilli(),
RequestFinishTime: 0, RequestFinishTime: 0,
UsedTime: 0, UsedTime: 0,
RestyResponse: nil, RestyResponse: nil,

View File

@ -125,3 +125,26 @@ func (r *Response) HttpSuccess(reqCfg *define.Request, response *define.Response
} }
return false return false
} }
// NeedRetry 是否需要重试
func (r *Response) NeedRetry(reqCfg *define.Request, response *define.Response) bool {
if nil == reqCfg.RetryRule {
// 未配置重试规则
return false
}
if reqCfg.RetryRule.RetryCount <= 0 {
// 未配置重试次数
return false
}
for _, httpCode := range reqCfg.RetryRule.RetryHttpCodeList {
if response.HttpCode == int(httpCode) {
return true
}
}
for _, businessCode := range reqCfg.RetryRule.RetryBusinessCodeList {
if businessCode == response.Code {
return true
}
}
return false
}