Files
GoProxy/optimizer/optimizer.go
isboyjc f55209d8d3 feat: init
2026-03-29 03:31:59 +08:00

109 lines
2.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}