Merge pull request 'feature/upgrade_retry' (#5) from feature/upgrade_retry into master
Reviewed-on: #5
This commit is contained in:
commit
5592e0a45c
@ -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
|
||||||
}
|
}
|
||||||
|
@ -19,26 +19,27 @@ import (
|
|||||||
//
|
//
|
||||||
// Date : 17:10 2024/5/24
|
// Date : 17:10 2024/5/24
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Ctx context.Context `json:"-"` // 请求上下文
|
Ctx context.Context `json:"-"` // 请求上下文
|
||||||
PathParam map[string]string `json:"path_param"` // 替换url中的占位符
|
PathParam map[string]string `json:"path_param"` // 替换url中的占位符
|
||||||
Body map[string]any `json:"body"` // 请求Body
|
Body map[string]any `json:"body"` // 请求Body
|
||||||
Header map[string]any `json:"header"` // 请求Header
|
Header map[string]any `json:"header"` // 请求Header
|
||||||
Cookie map[string]any `json:"cookie"` // 请求Cookie
|
Cookie map[string]any `json:"cookie"` // 请求Cookie
|
||||||
Query map[string]any `json:"query"` // 请求query
|
Query map[string]any `json:"query"` // 请求query
|
||||||
Static map[string]map[string]any `json:"static"` // 静态参数: location => valName => val
|
Static map[string]map[string]any `json:"static"` // 静态参数: location => valName => val
|
||||||
FullUrl string `json:"full_url"` // 完整的请求URL
|
FullUrl string `json:"full_url"` // 完整的请求URL
|
||||||
ContentType string `json:"content_type"` // 请求类型
|
ContentType string `json:"content_type"` // 请求类型
|
||||||
Method string `json:"method"` // 请求方法
|
Method string `json:"method"` // 请求方法
|
||||||
DataField string `json:"data_field"` // 数据字段
|
DataField string `json:"data_field"` // 数据字段
|
||||||
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部分数据解析
|
||||||
SuccessCodeList []string `json:"success_code_list"` // 哪些业务状态码视为成功
|
SuccessHttpCodeList []int `json:"success_http_code_list"` // 哪些http状态码视为成功, 不配置, 默认2xx
|
||||||
ConnectTimeout int64 `json:"connect_timeout"` // 连接超时时间: ms
|
SuccessCodeList []string `json:"success_code_list"` // 哪些业务状态码视为成功
|
||||||
ReadTimeout int64 `json:"read_timeout"` // 读取超时时间
|
ConnectTimeout int64 `json:"connect_timeout"` // 连接超时时间: ms
|
||||||
RetryRule *RequestRetryRule `json:"retry_rule"` // 重试规则
|
ReadTimeout int64 `json:"read_timeout"` // 读取超时时间
|
||||||
Logger *zap.Logger `json:"-"` // 日志记录器
|
RetryRule *RequestRetryRule `json:"retry_rule"` // 重试规则
|
||||||
RateLimiter resty.RateLimiter `json:"-"` // 流控实例
|
Logger *zap.Logger `json:"-"` // 日志记录器
|
||||||
|
RateLimiter resty.RateLimiter `json:"-"` // 流控实例
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestRetryRule 重试规则
|
// RequestRetryRule 重试规则
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user