mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-02-23 20:52:15 +08:00
refactor: 重构失败主动健康检测
This commit is contained in:
parent
f4d9384603
commit
fa9e27c5e4
@ -19,8 +19,10 @@ type GroupBase struct {
|
||||
providers []provider.ProxyProvider
|
||||
versions sync.Map // map[string]uint
|
||||
proxies sync.Map // map[string][]C.Proxy
|
||||
failedTimes *atomic.Int32
|
||||
failedTime *atomic.Int64
|
||||
failedTestMux sync.Mutex
|
||||
failedTimes int
|
||||
failedTime time.Time
|
||||
failedTesting *atomic.Bool
|
||||
}
|
||||
|
||||
type GroupBaseOption struct {
|
||||
@ -38,8 +40,7 @@ func NewGroupBase(opt GroupBaseOption) *GroupBase {
|
||||
Base: outbound.NewBase(opt.BaseOption),
|
||||
filter: filter,
|
||||
providers: opt.providers,
|
||||
failedTimes: atomic.NewInt32(-1),
|
||||
failedTime: atomic.NewInt64(-1),
|
||||
failedTesting: atomic.NewBool(false),
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,29 +106,45 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy {
|
||||
}
|
||||
|
||||
func (gb *GroupBase) onDialFailed() {
|
||||
if gb.failedTime.Load() == -1 {
|
||||
log.Warnln("%s first failed", gb.Name())
|
||||
now := time.Now().UnixMilli()
|
||||
gb.failedTime.Store(now)
|
||||
gb.failedTimes.Store(1)
|
||||
} else {
|
||||
if gb.failedTime.Load()-time.Now().UnixMilli() > gb.failedIntervalTime() {
|
||||
gb.failedTimes.Store(-1)
|
||||
gb.failedTime.Store(-1)
|
||||
} else {
|
||||
failedCount := gb.failedTimes.Inc()
|
||||
log.Warnln("%s failed count: %d", gb.Name(), failedCount)
|
||||
if failedCount >= gb.maxFailedTimes() {
|
||||
log.Warnln("because %s failed multiple times, active health check", gb.Name())
|
||||
for _, proxyProvider := range gb.providers {
|
||||
go proxyProvider.HealthCheck()
|
||||
if gb.failedTesting.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
gb.failedTimes.Store(-1)
|
||||
gb.failedTime.Store(-1)
|
||||
}
|
||||
go func() {
|
||||
gb.failedTestMux.Lock()
|
||||
defer func() {
|
||||
gb.failedTestMux.Unlock()
|
||||
}()
|
||||
|
||||
gb.failedTimes++
|
||||
if gb.failedTimes == 1 {
|
||||
log.Warnln("%s first failed", gb.Name())
|
||||
gb.failedTime = time.Now()
|
||||
} else {
|
||||
if time.Since(gb.failedTime) > gb.failedTimeoutInterval() {
|
||||
return
|
||||
}
|
||||
|
||||
log.Warnln("%s failed count: %d", gb.Name(), gb.failedTimes)
|
||||
if gb.failedTimes >= gb.maxFailedTimes() {
|
||||
gb.failedTesting.Store(true)
|
||||
log.Warnln("because %s failed multiple times, active health check", gb.Name())
|
||||
wg := sync.WaitGroup{}
|
||||
for _, proxyProvider := range gb.providers {
|
||||
wg.Add(1)
|
||||
proxyProvider := proxyProvider
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
proxyProvider.HealthCheck()
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
gb.failedTesting.Store(false)
|
||||
gb.failedTimes = 0
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (gb *GroupBase) failedIntervalTime() int64 {
|
||||
@ -135,10 +152,15 @@ func (gb *GroupBase) failedIntervalTime() int64 {
|
||||
}
|
||||
|
||||
func (gb *GroupBase) onDialSuccess() {
|
||||
gb.failedTimes.Store(-1)
|
||||
gb.failedTime.Store(-1)
|
||||
if !gb.failedTesting.Load() {
|
||||
gb.failedTimes = 0
|
||||
}
|
||||
}
|
||||
|
||||
func (gb *GroupBase) maxFailedTimes() int32 {
|
||||
func (gb *GroupBase) maxFailedTimes() int {
|
||||
return 5
|
||||
}
|
||||
|
||||
func (gb *GroupBase) failedTimeoutInterval() time.Duration {
|
||||
return 5 * time.Second
|
||||
}
|
||||
|
@ -37,8 +37,7 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
|
||||
c, err = u.fast(true).DialContext(ctx, metadata, u.Base.DialOptions(opts...)...)
|
||||
if err == nil {
|
||||
c.AppendToChains(u)
|
||||
u.failedTimes.Store(-1)
|
||||
u.failedTime.Store(-1)
|
||||
u.onDialSuccess()
|
||||
} else {
|
||||
u.onDialFailed()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user