- 添加 go-resty/v2依赖用于HTTP请求处理 - 创建代理配置模块 config/proxy.go 管理代理API地址和认证信息- 实现 SOCKS5代理结构体及缓存机制- 支持代理有效性测试与1分钟有效期管理 - 实现代理池缓存功能,支持最大50个代理缓存 - 添加代理获取重试机制(最多3次)- 更新 proxy controller 使用新的代理池系统 - 添加完整的单元测试覆盖代理功能 - 提供详细的 README 文档说明使用方法和API - 支持从环境变量配置代理认证信息 - 实现缓存清理和监控功能
简化的 SOCKS5 代理系统
这是一个简化的 SOCKS5 代理系统,支持按需获取代理、自动检测代理可用性、1分钟有效期管理等功能。
功能特性
- ✅ 按需从 API 获取 SOCKS5 代理
- ✅ 使用前自动检测代理可用性
- ✅ 1分钟有效期管理
- ✅ 自动重试机制(最多3次)
- ✅ 随机选择可用代理
- ✅ 支持用户名/密码认证
- ✅ 详细的日志记录
- ✅ 配置与实现分离
- ✅ 智能缓存机制 - 代理在有效期内可重复使用
- ✅ 缓存生命周期管理 - 3分钟未使用自动清理
- ✅ 缓存监控 - 实时查看缓存状态
文件结构
internal/proxy/
├── socks5.go # SOCKS5 代理实现
├── example.go # 使用示例
├── pool_test.go # 单元测试
└── README.md # 说明文档
internal/config/
└── proxy.go # 代理配置信息
使用方法
1. 基本使用
import (
"your-project/internal/proxy"
)
// 获取一个有效的代理(会自动重试)
socksProxy, err := proxy.GetValidProxy()
if err != nil {
return // 全局日志会自动记录错误
}
fmt.Printf("获取到代理: %s\n", socksProxy.Address())
2. 使用代理发送 HTTP 请求
import (
"net/http"
)
// 获取代理拨号器
dialer, err := socksProxy.GetDialer()
if err != nil {
log.Printf("创建代理拨号器失败: %v", err)
return
}
// 创建 HTTP 客户端
transport := &http.Transport{
DialContext: dialer.(proxy.ContextDialer).DialContext,
}
client := &http.Client{
Transport: transport,
Timeout: 30 * time.Second,
}
// 发送请求
resp, err := client.Get("https://httpbin.org/ip")
if err != nil {
log.Printf("请求失败: %v", err)
return
}
defer resp.Body.Close()
fmt.Printf("请求成功,状态码: %d\n", resp.StatusCode)
3. 创建自定义代理
// 创建 SOCKS5 代理
socksProxy := proxy.NewSocks5Proxy("127.0.0.1", "1080", "username", "password")
// 测试代理可用性
if socksProxy.Test() {
fmt.Println("代理可用")
} else {
fmt.Println("代理不可用")
}
// 检查代理是否过期
if socksProxy.IsExpired() {
fmt.Println("代理已过期")
}
4. 随机获取代理
// 获取一个随机代理(不检查过期)
socksProxy, err := proxy.GetRandomProxy()
if err != nil {
return // 全局日志会自动记录错误
}
// 手动检查代理有效性
if socksProxy.IsExpired() || !socksProxy.Test() {
return // 代理不可用,需要重新获取
}
配置
代理配置在 internal/config/proxy.go 中管理,通过环境变量设置:
# 代理获取 API 地址
export proxyUrl="https://share.proxy.qg.net/get?key=7ASQH2BI&num=2&area=&isp=0&format=txt&seq=\\r\\n&distinct=false"
# 代理认证密钥
export proxyAuthKey="7ASQH2BI"
# 代理认证密码
export proxyAuthPwd="34D6652FE7B6"
代理生命周期
- 有效期: 每个代理从创建开始有效期为 1 分钟
- 过期检测: 每次使用前都会检查代理是否过期
- 自动重试:
GetValidProxy会自动重试3次获取有效代理 - 实时测试: 每个代理在使用前都会进行连接性测试
缓存机制
缓存策略
- 优先缓存:
GetValidProxy优先从缓存获取代理 - 智能过期: 代理有效期1分钟,缓存有效期3分钟
- 自动清理: 3分钟未使用的代理自动从缓存清除
- 最大容量: 缓存最多保存50个代理
- 线程安全: 使用读写锁保证并发安全
缓存管理
// 获取缓存统计信息
total, valid, tested := proxy.GetCacheInfo()
fmt.Printf("缓存状态 - 总数: %d, 有效: %d, 已测试: %d\n", total, valid, tested)
// 手动清理过期缓存
proxy.CleanCache()
缓存优势
- 性能提升: 避免重复调用API获取代理
- 减少延迟: 从缓存获取代理几乎无延迟
- 智能重用: 有效期内代理可重复使用
- 自动管理: 过期代理自动清理
- 监控友好: 提供缓存统计信息
缓存工作流程
- 首次请求: 从API获取代理,添加到缓存
- 后续请求: 优先从缓存获取有效代理
- 代理测试: 缓存中的代理会实时测试可用性
- 过期清理: 过期或无效代理自动清理
- 容量管理: 超过最大容量时自动清理最旧代理
API 说明
主要函数
GetValidProxy() (*Socks5Proxy, error)- 获取有效代理(优先从缓存)GetRandomProxy() (*Socks5Proxy, error)- 获取随机代理NewSocks5Proxy(host, port, username, password) *Socks5Proxy- 创建自定义代理
缓存管理函数
GetCacheInfo() (total, valid, tested int)- 获取缓存统计信息CleanCache()- 手动清理过期缓存
Socks5Proxy 方法
Test() bool- 测试代理可用性IsExpired() bool- 检查是否过期Address() string- 获取代理地址字符串GetDialer() (proxy.Dialer, error)- 获取 SOCKS5 拨号器
简化特性
相比复杂的代理池,这个简化版本有以下特点:
- 按需获取 - 只在需要时才从 API 获取代理
- 无状态管理 - 不维护复杂的代理池状态
- 自动重试 - 内置重试机制,无需手动管理
- 简单过期 - 基于创建时间的简单过期逻辑
- 配置分离 - 配置信息在独立的 config 包中
测试
运行测试:
# 运行所有测试
go test ./internal/proxy/...
# 运行测试并显示详细输出
go test -v ./internal/proxy/...
# 运行基准测试
go test -bench=. ./internal/proxy/...
日志
系统使用 zap 日志库记录详细操作日志:
- 代理获取过程和结果
- 代理测试成功/失败
- 重试过程
- 错误信息
注意事项
- 网络依赖: 需要网络连接访问代理 API
- 认证信息: 确保 API 认证信息正确
- 超时设置: 默认10秒超时,可根据需要调整
- 1分钟限制: 代理有效期固定为1分钟,过期需重新获取
示例应用
参考 example.go 文件中的完整示例,了解如何在实际应用中使用简化的代理系统。