refactor(proxy): 使用resty简化代理获取和检测逻辑

- 将 DefaultProxyStrategy 和 OrderBasedProxyStrategy 的 HTTP 请求客户端改为 resty
- 替换 http.Client 请求代码,使用 resty 支持的链式调用和上下文传递
- 调整代理可用性检测,使用 resty 并检测响应成功状态
- 在获取代理失败时添加错误日志记录,增加异常可追踪性
- 缩短请求超时时间,优化网络请求性能
- 删除多余的手动读写响应体代码,简化逻辑实现
This commit is contained in:
danial
2025-12-09 01:22:49 +08:00
parent 39b0b5f795
commit 08f5488ba9
2 changed files with 28 additions and 118 deletions

View File

@@ -107,8 +107,9 @@ func (s *SendCardTaskTypeFlyFishV2) HandleSendCardTask(ctx context.Context, orde
SetHeader("origin", "https://apify.fkpay.online").
SetHeader("user-agent", useragent.GetUserAgentByPlatform(useragent.PlatformPhone)).
SetHeader("referer", "https://apify.fkpay.online/show.html?orderId=FY17568845864231914279").
SetTimeout(time.Second * 20).OnBeforeRequest(func(client *resty.Client, request *resty.Request) error {
proxy, _ := utils.GetProxy(ctx, utils.GenerateId(), "SendCardTaskTypeFlyFishV2_cardTask")
SetTimeout(time.Second * 10).OnBeforeRequest(func(client *resty.Client, request *resty.Request) error {
proxy, err2 := utils.GetProxy(ctx, utils.GenerateId(), "SendCardTaskTypeFlyFishV2_cardTask")
otelTrace.Logger.WithContext(ctx).Error("获取代理失败", zap.Error(err2))
if proxy != "" {
client.SetProxy(proxy)
}

View File

@@ -2,14 +2,15 @@ package utils
import (
"context"
"errors"
"fmt"
"io"
"github.com/dubonzi/otelresty"
"github.com/go-resty/resty/v2"
"maps"
"math/rand/v2"
"net/http"
"net/url"
"slices"
"strings"
"sync"
"time"
@@ -17,10 +18,8 @@ import (
"gateway/internal/config"
"gateway/internal/otelTrace"
"github.com/duke-git/lancet/v2/netutil"
"github.com/duke-git/lancet/v2/slice"
"github.com/duke-git/lancet/v2/strutil"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"go.uber.org/zap"
@@ -371,78 +370,24 @@ func (p *OrderBasedProxyStrategy) createHTTPClient(proxy string) (*http.Client,
// tryGetProxy 尝试获取代理IP
func (p *DefaultProxyStrategy) tryGetProxy(ctx context.Context) (string, error) {
client := &http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport),
Timeout: 2 * time.Second,
}
encodedUrl, err := netutil.EncodeUrl(p.proxyURL)
if err != nil {
return "", fmt.Errorf("编码代理URL失败: %v", err)
}
req, err := http.NewRequestWithContext(ctx, "GET", encodedUrl, nil)
if err != nil {
return "", fmt.Errorf("创建请求失败: %v", err)
}
resp, err := client.Do(req)
client := resty.New()
otelresty.TraceClient(client)
proxyURL, err := client.R().SetContext(ctx).Get(p.proxyURL)
if err != nil {
return "", fmt.Errorf("请求代理服务失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("读取响应失败: %v", err)
}
proxyIP := strings.TrimSpace(string(body))
otelTrace.Logger.WithContext(ctx).Info("获取代理IP", zap.String("proxyIP", proxyIP))
if proxyIP == "" {
return "", fmt.Errorf("获取代理IP失败")
}
if err = p.checkProxyAvailable(ctx, proxyIP); err != nil {
return "", fmt.Errorf("代理IP不可用: %v", err)
}
return proxyIP, nil
return proxyURL.String(), nil
}
// tryGetProxy 尝试获取代理IP
func (p *OrderBasedProxyStrategy) tryGetProxy(ctx context.Context) ([]string, error) {
client := &http.Client{
Timeout: 5 * time.Second,
}
proxyURL, err := netutil.EncodeUrl(p.proxyURL)
if err != nil {
return []string{}, fmt.Errorf("解析代理URL失败: %v", err)
}
req, err := http.NewRequestWithContext(ctx, "GET", proxyURL, nil)
if err != nil {
return []string{}, fmt.Errorf("创建请求失败: %v", err)
}
resp, err := client.Do(req)
client := resty.New()
otelresty.TraceClient(client)
proxyURL, err := client.R().SetContext(ctx).Get(p.proxyURL)
if err != nil {
return []string{}, fmt.Errorf("请求代理服务失败: %v", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return []string{}, fmt.Errorf("读取响应失败: %v", err)
}
proxyIP := strings.TrimSpace(string(body))
otelTrace.Logger.WithContext(ctx).Info("获取代理IP", zap.String("proxyIP", proxyIP))
if proxyIP == "" {
return []string{}, fmt.Errorf("获取代理IP失败")
}
proxyIPs := strutil.SplitAndTrim(proxyIP, "\n")
proxyIPs := strutil.SplitAndTrim(proxyURL.String(), "\n")
slice.ForEach(proxyIPs, func(index int, item string) {
proxyIPs[index] = strutil.Trim(item)
@@ -452,68 +397,32 @@ func (p *OrderBasedProxyStrategy) tryGetProxy(ctx context.Context) ([]string, er
// checkProxyAvailable 检查代理IP是否可用
func (p *DefaultProxyStrategy) checkProxyAvailable(ctx context.Context, proxyIP string) error {
proxyURL, err := url.Parse(fmt.Sprintf("socks5://%s:%s@%s", p.authKey, p.authPwd, proxyIP))
if err != nil {
return fmt.Errorf("解析代理URL失败: %v", err)
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyURL),
}
client := &http.Client{
Transport: transport,
Timeout: 2 * time.Second,
}
req, err := http.NewRequestWithContext(ctx, "GET", "https://www.baidu.com", nil)
if err != nil {
return fmt.Errorf("创建测试请求失败: %v", err)
}
resp, err := client.Do(req)
client := resty.New()
otelresty.TraceClient(client)
client.SetProxy(fmt.Sprintf("socks5://%s:%s@%s", p.authKey, p.authPwd, proxyIP))
response, err := client.R().SetContext(ctx).Get("https://www.qq.com")
if err != nil {
return fmt.Errorf("代理连接测试失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("代理响应状态码异常: %d", resp.StatusCode)
if response.IsSuccess() {
return nil
}
return nil
return errors.New("代理响应状态码异常")
}
// checkProxyAvailable 检查代理IP是否可用
func (p *OrderBasedProxyStrategy) checkProxyAvailable(ctx context.Context, proxyIP string) error {
proxyURL, err := url.Parse(fmt.Sprintf("socks5://%s:%s@%s", p.authKey, p.authPwd, proxyIP))
if err != nil {
return fmt.Errorf("解析代理URL失败: %v", err)
}
client := http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
Timeout: 2 * time.Second,
}
req, err := http.NewRequestWithContext(ctx, "GET", "https://www.baidu.com", nil)
if err != nil {
return fmt.Errorf("创建测试请求失败: %v", err)
}
resp, err := client.Do(req)
client := resty.New()
otelresty.TraceClient(client)
client.SetProxy(fmt.Sprintf("socks5://%s:%s@%s", p.authKey, p.authPwd, proxyIP))
response, err := client.R().SetContext(ctx).Get("https://www.qq.com")
if err != nil {
return fmt.Errorf("代理连接测试失败: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("代理响应状态码异常: %d", resp.StatusCode)
if response.IsSuccess() {
return nil
}
return nil
return errors.New("代理响应状态码异常")
}
// startCleanupRoutine 启动清理协程