From b335d7c2bbdf83852cfef69dcd4bdb29bfbb1f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 7 May 2025 16:32:20 +0800 Subject: [PATCH] =?UTF-8?q?IResponse=E7=BA=A6=E6=9D=9F=E5=A2=9E=E5=8A=A0Ne?= =?UTF-8?q?edRetry=E6=98=AF=E5=90=A6=E9=9C=80=E8=A6=81=E9=87=8D=E8=AF=95?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- httpclient/abstract/IResponse.go | 2 ++ httpclient/client.go | 50 +++++++++++++------------------- httpclient/implement/response.go | 23 +++++++++++++++ 3 files changed, 45 insertions(+), 30 deletions(-) diff --git a/httpclient/abstract/IResponse.go b/httpclient/abstract/IResponse.go index 5a11f7a..0605571 100644 --- a/httpclient/abstract/IResponse.go +++ b/httpclient/abstract/IResponse.go @@ -27,4 +27,6 @@ type IResponse interface { BusinessSuccess(reqCfg *define.Request, response *define.Response) bool // HttpSuccess http状态码是否成功 HttpSuccess(reqCfg *define.Request, response *define.Response) bool + // NeedRetry 是否需要重试 + NeedRetry(reqCfg *define.Request, response *define.Response) bool } diff --git a/httpclient/client.go b/httpclient/client.go index 4e02e57..b90c6c7 100644 --- a/httpclient/client.go +++ b/httpclient/client.go @@ -345,38 +345,22 @@ func (hc *HttpClient) requestBackendApi() *define.Response { err error ) - response := hc.newResponse() + var response *define.Response + // +1 是因为正常便会请求一次, 正常请求1次 + 重试次数 = 请求总次数 for i := 0; i < hc.reqCfg.RetryRule.RetryCount+1; i++ { - if i > 0 { - // 非首次请求, 说明是重试, 暂停指定时间间隔 - time.Sleep(time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond) - } - if response.Seq > 0 { + if i > 0 && nil != response { // 说明是重试, 记录上一次的请求信息 response.RequestFinishTime = time.Now().UnixMilli() response.UsedTime = response.RequestFinishTime - response.RequestStartTime for _, itemAfterResponse := range hc.requestFinishHandler { itemAfterResponse(hc.reqCfg, response) } + // 非首次请求, 说明是重试, 暂停指定时间间隔 + time.Sleep(time.Duration(hc.reqCfg.RetryRule.RetryTimeInterval) * time.Millisecond) } - response.RequestStartTime = time.Now().UnixMilli() // 每次重置请求时间 - response.RequestFinishTime = 0 // 清空完成时间 - response.Seq++ - 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 - } + response = hc.newResponse() + response.Seq = i + response.RequestCount = i + 1 if response.RestyResponse, err = hc.request.Send(); nil != err { errType := define.RequestFailTypeSend if err.Error() == resty.ErrRateLimitExceeded.Error() { @@ -386,6 +370,9 @@ func (hc *HttpClient) requestBackendApi() *define.Response { if netErr.Timeout() { // 请求超时 errType = define.RequestFailTypeTimeoutError + // 重置响应状态码 + response.HttpCode = 499 + response.HttpCodeStatus = "request timeout" } } response.FailInfo = &define.ResponseFailInfo{ @@ -402,7 +389,7 @@ func (hc *HttpClient) requestBackendApi() *define.Response { break } - if errType == define.RequestFailTypeTimeoutError && !retryHttpCodeTable[499] { + if errType == define.RequestFailTypeTimeoutError && !hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response) { // 未配置超时重试 log.RecordDebug("请求超时, 未配置超时重试, 不进行重试", nil, hc.reqCfg) break @@ -441,15 +428,16 @@ func (hc *HttpClient) requestBackendApi() *define.Response { Type: errType, Message: "http code is " + response.HttpCodeStatus + ", not success", } + needRetry := hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response) log.RecordWarn("请求响应的http状态码非成功", map[string]any{ "err_type": errType, "err_msg": response.RestyResponse.Status(), "response_http_code": response.HttpCode, "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, }, hc.reqCfg) - if len(retryHttpCodeTable) > 0 && !retryHttpCodeTable[int64(response.HttpCode)] { + if !needRetry { // 未配置http code重试 break } @@ -460,15 +448,17 @@ func (hc *HttpClient) requestBackendApi() *define.Response { Type: define.RequestFailTypeBusinessError, Message: "business code is " + response.Code + ", not success", } + needRetry := hc.reqOption.ResponseParser.NeedRetry(hc.reqCfg, response) + log.RecordWarn("请求响应状态码成功, 业务状态码非成功", map[string]any{ "err_type": response.FailInfo.Type, "err_msg": response.Message, "response_code": response.Code, "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, }, hc.reqCfg) - if len(retryBusinessCodeTable) > 0 && !retryBusinessCodeTable[response.Code] { + if needRetry { // 未配置业务code重试 break } @@ -504,7 +494,7 @@ func (hc *HttpClient) newResponse() *define.Response { HttpCodeStatus: "", ResponseDataRule: nil, Seq: 0, - RequestStartTime: 0, + RequestStartTime: time.Now().UnixMilli(), RequestFinishTime: 0, UsedTime: 0, RestyResponse: nil, diff --git a/httpclient/implement/response.go b/httpclient/implement/response.go index e3168f9..1a73ba2 100644 --- a/httpclient/implement/response.go +++ b/httpclient/implement/response.go @@ -125,3 +125,26 @@ func (r *Response) HttpSuccess(reqCfg *define.Request, response *define.Response } 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 +}