Merge pull request 'feature/upgrade_retry' (#5) from feature/upgrade_retry into master

Reviewed-on: #5
This commit is contained in:
白茶清欢 2025-04-17 18:43:42 +08:00
commit 5592e0a45c
3 changed files with 64 additions and 23 deletions

View File

@ -10,7 +10,6 @@ package httpclient
import ( import (
"fmt" "fmt"
"net" "net"
"net/http"
"strings" "strings"
"time" "time"
@ -37,6 +36,18 @@ func NewHttpClient(reqConfig *define.Request, cacheInstance cache.ICache) (*Http
if err := validate.RequestConfig(reqConfig); nil != err { if err := validate.RequestConfig(reqConfig); nil != err {
return nil, err return nil, err
} }
if reqConfig.RetryRule == nil {
reqConfig.RetryRule = &define.RequestRetryRule{
RetryCount: 0,
RetryTimeInterval: 0,
RetryHttpCodeList: []int64{},
RetryBusinessCodeList: []string{},
} // 未指定重试规则, 则使用默认重试规则
}
// 初始化成功的 http code list
if len(reqConfig.SuccessHttpCodeList) == 0 {
reqConfig.SuccessHttpCodeList = []int{}
}
if len(reqConfig.Static) > 0 { if len(reqConfig.Static) > 0 {
for loc, valMap := range reqConfig.Static { for loc, valMap := range reqConfig.Static {
if len(valMap) == 0 { if len(valMap) == 0 {
@ -276,6 +287,20 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
response.RequestFinishTime = 0 // 清空完成时间 response.RequestFinishTime = 0 // 清空完成时间
response.Seq++ response.Seq++
response.RequestCount++ response.RequestCount++
retryHttpCodeTable := make(map[int64]bool)
retryBusinessCodeTable := make(map[string]bool)
if nil != hc.reqConfig.RetryRule {
for _, httpCode := range hc.reqConfig.RetryRule.RetryHttpCodeList {
retryHttpCodeTable[httpCode] = true
}
for _, businessCode := range hc.reqConfig.RetryRule.RetryBusinessCodeList {
retryBusinessCodeTable[businessCode] = true
}
}
successHttpCodeTable := make(map[int]bool)
for _, itemHttpCode := range hc.reqConfig.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() {
@ -293,6 +318,10 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
// 命中限流就不重试了 // 命中限流就不重试了
break break
} }
if len(retryHttpCodeTable) > 0 && !retryHttpCodeTable[499] {
// 未配置超时重试
break
}
time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond) time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond)
continue continue
} }
@ -309,7 +338,10 @@ func (hc *HttpClient) requestBackendApi() *define.Response {
hc.fillResponseHeader(response) hc.fillResponseHeader(response)
hc.fillResponseCookie(response) hc.fillResponseCookie(response)
hc.fillResponseBody(response) hc.fillResponseBody(response)
if response.HttpCode != http.StatusOK { // 配置了当前code为成功, 或者未配置任何code, 当前code为2xx, 则认为请求成功
isHttpSuccess := successHttpCodeTable[response.HttpCode] || (len(successHttpCodeTable) == 0 && response.HttpCode/100 == 2)
if !isHttpSuccess {
// 非 成功
errType := define.RequestFailTypeServerError errType := define.RequestFailTypeServerError
if response.HttpCode/100 == 4 { if response.HttpCode/100 == 4 {
// 客户端错误 // 客户端错误
@ -319,6 +351,10 @@ 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",
} }
if len(retryHttpCodeTable) > 0 && !retryHttpCodeTable[int64(response.HttpCode)] {
// 未配置http code重试
break
}
time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond) time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond)
continue continue
} }
@ -327,6 +363,10 @@ 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",
} }
if len(retryBusinessCodeTable) > 0 && !retryBusinessCodeTable[response.Code] {
// 未配置业务code重试
break
}
time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond) time.Sleep(time.Duration(hc.reqConfig.RetryRule.RetryTimeInterval) * time.Millisecond)
continue continue
} }

View File

@ -33,6 +33,7 @@ type Request struct {
CodeField string `json:"code_field"` // 业务状态码字段 CodeField string `json:"code_field"` // 业务状态码字段
MessageField string `json:"message_field"` // code描述字段 MessageField string `json:"message_field"` // code描述字段
DataReceiver any `json:"-"` // 响应data部分数据解析 DataReceiver any `json:"-"` // 响应data部分数据解析
SuccessHttpCodeList []int `json:"success_http_code_list"` // 哪些http状态码视为成功, 不配置, 默认2xx
SuccessCodeList []string `json:"success_code_list"` // 哪些业务状态码视为成功 SuccessCodeList []string `json:"success_code_list"` // 哪些业务状态码视为成功
ConnectTimeout int64 `json:"connect_timeout"` // 连接超时时间: ms ConnectTimeout int64 `json:"connect_timeout"` // 连接超时时间: ms
ReadTimeout int64 `json:"read_timeout"` // 读取超时时间 ReadTimeout int64 `json:"read_timeout"` // 读取超时时间

View File

@ -63,7 +63,7 @@ func NewRestyClient(reqConfig *define.Request) (*resty.Client, *resty.Request) {
if len(pathParamValue) == 0 { if len(pathParamValue) == 0 {
continue continue
} }
reqConfig.FullUrl = strings.ReplaceAll(reqConfig.FullUrl, "{#"+pathParamName+"#}", pathParamValue) reqConfig.FullUrl = strings.ReplaceAll(reqConfig.FullUrl, "{"+pathParamName+"}", pathParamValue)
} }
request.Method = reqConfig.Method // 请求方法 request.Method = reqConfig.Method // 请求方法
cookieList := make([]*http.Cookie, 0) cookieList := make([]*http.Cookie, 0)