mirror of
https://github.com/isboyjc/GoProxy.git
synced 2026-05-07 04:22:43 +08:00
109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
package optimizer
|
||
|
||
import (
|
||
"log"
|
||
"time"
|
||
|
||
"goproxy/config"
|
||
"goproxy/fetcher"
|
||
"goproxy/pool"
|
||
"goproxy/storage"
|
||
"goproxy/validator"
|
||
)
|
||
|
||
// Optimizer 优化轮换器
|
||
type Optimizer struct {
|
||
storage *storage.Storage
|
||
fetcher *fetcher.Fetcher
|
||
validator *validator.Validator
|
||
poolMgr *pool.Manager
|
||
cfg *config.Config
|
||
}
|
||
|
||
func NewOptimizer(s *storage.Storage, f *fetcher.Fetcher, v *validator.Validator, pm *pool.Manager, cfg *config.Config) *Optimizer {
|
||
return &Optimizer{
|
||
storage: s,
|
||
fetcher: f,
|
||
validator: v,
|
||
poolMgr: pm,
|
||
cfg: cfg,
|
||
}
|
||
}
|
||
|
||
// RunOnce 执行一次优化轮换
|
||
func (o *Optimizer) RunOnce() {
|
||
start := time.Now()
|
||
log.Println("[optimize] 🎯 开始优化轮换...")
|
||
|
||
// 获取池子状态
|
||
status, err := o.poolMgr.GetStatus()
|
||
if err != nil {
|
||
log.Printf("[optimize] 获取状态失败: %v", err)
|
||
return
|
||
}
|
||
|
||
// 只有健康状态才执行优化
|
||
if status.State != "healthy" {
|
||
log.Printf("[optimize] 池子状态 %s,跳过优化", status.State)
|
||
return
|
||
}
|
||
|
||
// 抓取新的候选代理(优化模式)
|
||
log.Println("[optimize] 抓取新候选代理...")
|
||
candidates, err := o.fetcher.FetchSmart("optimize", "")
|
||
if err != nil {
|
||
log.Printf("[optimize] 抓取失败: %v", err)
|
||
return
|
||
}
|
||
|
||
log.Printf("[optimize] 抓取到 %d 个候选代理", len(candidates))
|
||
|
||
// 验证候选代理
|
||
validCandidates := []storage.Proxy{}
|
||
for result := range o.validator.ValidateStream(candidates) {
|
||
if result.Valid {
|
||
latencyMs := int(result.Latency.Milliseconds())
|
||
// 只保留延迟在健康标准内的
|
||
if latencyMs <= o.cfg.MaxLatencyHealthy {
|
||
validCandidates = append(validCandidates, storage.Proxy{
|
||
Address: result.Proxy.Address,
|
||
Protocol: result.Proxy.Protocol,
|
||
ExitIP: result.ExitIP,
|
||
ExitLocation: result.ExitLocation,
|
||
Latency: latencyMs,
|
||
})
|
||
}
|
||
}
|
||
}
|
||
|
||
log.Printf("[optimize] 验证通过 %d 个优质候选(延迟<%dms)", len(validCandidates), o.cfg.MaxLatencyHealthy)
|
||
|
||
if len(validCandidates) == 0 {
|
||
log.Println("[optimize] 无优质候选,跳过优化")
|
||
return
|
||
}
|
||
|
||
// 尝试用优质候选替换延迟高的代理
|
||
replacedCount := 0
|
||
for _, candidate := range validCandidates {
|
||
added, reason := o.poolMgr.TryAddProxy(candidate)
|
||
if added && reason == "replaced" {
|
||
replacedCount++
|
||
}
|
||
}
|
||
|
||
elapsed := time.Since(start)
|
||
log.Printf("[optimize] ✅ 完成: 替换 %d 个代理 耗时%v", replacedCount, elapsed)
|
||
}
|
||
|
||
// StartBackground 后台定时优化
|
||
func (o *Optimizer) StartBackground() {
|
||
ticker := time.NewTicker(time.Duration(o.cfg.OptimizeInterval) * time.Minute)
|
||
go func() {
|
||
for range ticker.C {
|
||
o.RunOnce()
|
||
}
|
||
}()
|
||
log.Printf("[optimize] 优化轮换器已启动,间隔 %d 分钟", o.cfg.OptimizeInterval)
|
||
}
|