|
@@ -3,73 +3,63 @@ package client
|
|
|
import (
|
|
|
"context"
|
|
|
"fmt"
|
|
|
- "io/ioutil"
|
|
|
+ "io"
|
|
|
"log"
|
|
|
"net/http"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
type HttpClient struct {
|
|
|
- client *http.Client
|
|
|
- maxRetries int
|
|
|
- retryDelay time.Duration
|
|
|
+ *http.Client
|
|
|
+ maxRetries int
|
|
|
+ retryDelayFunc RetryDelayFunc
|
|
|
}
|
|
|
|
|
|
func GetInstance(timeout time.Duration, maxRetries int) *HttpClient {
|
|
|
return &HttpClient{
|
|
|
- client: &http.Client{Timeout: timeout},
|
|
|
- maxRetries: maxRetries,
|
|
|
+ Client: &http.Client{Timeout: timeout},
|
|
|
+ maxRetries: maxRetries,
|
|
|
+ retryDelayFunc: defaultRetryDelayFunc,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func defaultRetryDelayFunc(attempt int) time.Duration {
|
|
|
+ delay := time.Duration(attempt) * time.Second
|
|
|
+ if attempt > 0 {
|
|
|
+ delay *= 2
|
|
|
+ }
|
|
|
+ return delay
|
|
|
+}
|
|
|
+
|
|
|
type RetryDelayFunc func(attempt int) time.Duration
|
|
|
|
|
|
// DoWithRetry 发送带有重试机制的HTTP请求,允许用户自定义重试延迟逻辑
|
|
|
-func (hc *HttpClient) DoWithRetry(ctx context.Context, req *http.Request, retryDelayFunc RetryDelayFunc) (*http.Response, error) {
|
|
|
+func (hc *HttpClient) DoWithRetry(ctx context.Context, req *http.Request) (*http.Response, error) {
|
|
|
attempt := 0
|
|
|
for {
|
|
|
- resp, err := hc.client.Do(req.WithContext(ctx))
|
|
|
+ resp, err := hc.Do(req.WithContext(ctx))
|
|
|
if err != nil {
|
|
|
if attempt >= hc.maxRetries {
|
|
|
return nil, fmt.Errorf("请求失败: %w", err)
|
|
|
}
|
|
|
attempt++
|
|
|
- delay := retryDelayFunc(attempt)
|
|
|
+ delay := hc.retryDelayFunc(attempt)
|
|
|
time.Sleep(delay)
|
|
|
continue
|
|
|
}
|
|
|
return resp, nil
|
|
|
}
|
|
|
}
|
|
|
-func main() {
|
|
|
- client := GetInstance(10*time.Second, 3) // 超时10秒,最多重试3次
|
|
|
|
|
|
- // 自定义重试延迟逻辑
|
|
|
- customRetryDelay := func(attempt int) time.Duration {
|
|
|
- // 示例:首次重试立即进行,之后每次重试等待时间加倍
|
|
|
- delay := time.Duration(attempt) * time.Second
|
|
|
- if attempt > 0 {
|
|
|
- delay *= 2
|
|
|
- }
|
|
|
- return delay
|
|
|
- }
|
|
|
+func (hc *HttpClient) Post(url string, contentType string, buf io.Reader) (resp *http.Response, err error) {
|
|
|
+ return
|
|
|
+}
|
|
|
|
|
|
- url := "http://example.com/api/data"
|
|
|
+func (hc *HttpClient) Get(url string) (resp *http.Response, err error) {
|
|
|
req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil)
|
|
|
if err != nil {
|
|
|
log.Fatalf("创建请求失败: %v", err)
|
|
|
}
|
|
|
-
|
|
|
- resp, err := client.DoWithRetry(req.Context(), req, customRetryDelay)
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("%v,请求失败", err)
|
|
|
- }
|
|
|
- defer resp.Body.Close()
|
|
|
-
|
|
|
- body, readErr := ioutil.ReadAll(resp.Body)
|
|
|
- if readErr != nil {
|
|
|
- log.Fatalf("解析应答失败: %v", readErr)
|
|
|
- }
|
|
|
-
|
|
|
- fmt.Printf("应答结果为: %s\n", body)
|
|
|
+ resp, err = hc.DoWithRetry(req.Context(), req)
|
|
|
+ return
|
|
|
}
|