fix: when connection refused active health test

This commit is contained in:
Skyxim
2022-10-16 13:12:49 +08:00
parent 023e3d0c41
commit 0fb0e490f8
5 changed files with 47 additions and 22 deletions

View File

@ -31,7 +31,7 @@ func (f *Fallback) DialContext(ctx context.Context, metadata *C.Metadata, opts .
c.AppendToChains(f)
f.onDialSuccess()
} else {
f.onDialFailed()
f.onDialFailed(proxy.Type(), err)
}
return c, err

View File

@ -11,6 +11,7 @@ import (
"github.com/Dreamacro/clash/tunnel"
"github.com/dlclark/regexp2"
"go.uber.org/atomic"
"strings"
"sync"
"time"
)
@ -136,8 +137,13 @@ func (gb *GroupBase) URLTest(ctx context.Context, url string) (map[string]uint16
}
}
func (gb *GroupBase) onDialFailed() {
if gb.failedTesting.Load() {
func (gb *GroupBase) onDialFailed(adapterType C.AdapterType, err error) {
if adapterType == C.Direct || adapterType == C.Compatible || adapterType == C.Reject || adapterType == C.Pass {
return
}
if strings.Contains(err.Error(), "connection refused") {
go gb.healthCheck()
return
}
@ -157,26 +163,34 @@ func (gb *GroupBase) onDialFailed() {
log.Debugln("ProxyGroup: %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
gb.healthCheck()
}
}
}()
}
func (gb *GroupBase) healthCheck() {
if gb.failedTesting.Load() {
return
}
gb.failedTesting.Store(true)
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 {
return 5 * time.Second.Milliseconds()
}

View File

@ -82,17 +82,17 @@ func jumpHash(key uint64, buckets int32) int32 {
// DialContext implements C.ProxyAdapter
func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (c C.Conn, err error) {
proxy := lb.Unwrap(metadata)
defer func() {
if err == nil {
c.AppendToChains(lb)
lb.onDialSuccess()
} else {
lb.onDialFailed()
lb.onDialFailed(proxy.Type(), err)
}
}()
proxy := lb.Unwrap(metadata)
c, err = proxy.DialContext(ctx, metadata, lb.Base.DialOptions(opts...)...)
return
}

View File

@ -34,12 +34,13 @@ func (u *URLTest) Now() string {
// DialContext implements C.ProxyAdapter
func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (c C.Conn, err error) {
c, err = u.fast(true).DialContext(ctx, metadata, u.Base.DialOptions(opts...)...)
proxy := u.fast(true)
c, err = proxy.DialContext(ctx, metadata, u.Base.DialOptions(opts...)...)
if err == nil {
c.AppendToChains(u)
u.onDialSuccess()
} else {
u.onDialFailed()
u.onDialFailed(proxy.Type(), err)
}
return c, err
}