mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 09:25:41 +08:00
strategy: added new option checkfailedonly #138
This commit is contained in:
parent
149824cc20
commit
0b0611a0dc
1
conf.go
1
conf.go
@ -43,6 +43,7 @@ func confInit() {
|
||||
flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "proxy check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
|
||||
flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "proxy check interval(seconds)")
|
||||
flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "proxy check timeout(seconds)")
|
||||
flag.BoolVar(&conf.StrategyConfig.CheckFailedOnly, "checkfailedonly", false, "check failed fowarder only")
|
||||
flag.IntVar(&conf.StrategyConfig.MaxFailures, "maxfailures", 3, "max failures to change forwarder status to disabled")
|
||||
flag.StringVar(&conf.StrategyConfig.IntFace, "interface", "", "source ip or source interface")
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -10,9 +10,9 @@ require (
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.3.0 // indirect
|
||||
github.com/xtaci/kcp-go/v5 v5.5.12
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904
|
||||
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f // indirect
|
||||
)
|
||||
|
||||
// Replace dependency modules with local developing copy
|
||||
|
8
go.sum
8
go.sum
@ -58,8 +58,8 @@ golang.org/x/crypto v0.0.0-20191010185427-af544f31c8ac/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
|
||||
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 h1:IhZPbxNd1UjBCaD5AfpSSbJTRlp+ZSuyuH5uoksNS04=
|
||||
golang.org/x/crypto v0.0.0-20200420104511-884d27f42877/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -73,8 +73,8 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191020212454-3e7259c5e7c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -17,12 +17,13 @@ import (
|
||||
|
||||
// Config is strategy config struct.
|
||||
type Config struct {
|
||||
Strategy string
|
||||
CheckWebSite string
|
||||
CheckInterval int
|
||||
CheckTimeout int
|
||||
MaxFailures int
|
||||
IntFace string
|
||||
Strategy string
|
||||
CheckWebSite string
|
||||
CheckInterval int
|
||||
CheckTimeout int
|
||||
CheckFailedOnly bool
|
||||
MaxFailures int
|
||||
IntFace string
|
||||
}
|
||||
|
||||
// forwarder slice orderd by priority
|
||||
@ -185,66 +186,96 @@ func (p *Proxy) Check() {
|
||||
// no need to check when there's only 1 forwarder
|
||||
if len(p.fwdrs) > 1 {
|
||||
for i := 0; i < len(p.fwdrs); i++ {
|
||||
go p.check(i)
|
||||
go p.check(p.fwdrs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Proxy) check(i int) {
|
||||
f := p.fwdrs[i]
|
||||
retry := 1
|
||||
func (p *Proxy) check(f *Forwarder) {
|
||||
wait := uint8(0)
|
||||
buf := make([]byte, 4)
|
||||
intval := time.Duration(p.config.CheckInterval) * time.Second
|
||||
|
||||
for {
|
||||
time.Sleep(time.Duration(p.config.CheckInterval) * time.Second * time.Duration(retry>>1))
|
||||
time.Sleep(intval * time.Duration(wait))
|
||||
|
||||
// check all forwarders at least one time
|
||||
if retry > 1 && f.Priority() < p.Priority() {
|
||||
if wait > 0 && (f.Priority() < p.Priority()) {
|
||||
continue
|
||||
}
|
||||
|
||||
retry <<= 1
|
||||
if retry > 16 {
|
||||
retry = 16
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
rc, err := f.Dial("tcp", p.config.CheckWebSite)
|
||||
if err != nil {
|
||||
f.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err)
|
||||
if f.Enabled() && p.config.CheckFailedOnly {
|
||||
continue
|
||||
}
|
||||
|
||||
rc.Write([]byte("GET / HTTP/1.0\r\n\r\n"))
|
||||
|
||||
_, err = io.ReadFull(rc, buf)
|
||||
if err != nil {
|
||||
f.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, err)
|
||||
} else if bytes.Equal([]byte("HTTP"), buf) {
|
||||
|
||||
readTime := time.Since(startTime)
|
||||
f.SetLatency(int64(readTime))
|
||||
|
||||
if readTime > time.Duration(p.config.CheckTimeout)*time.Second {
|
||||
f.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
|
||||
} else {
|
||||
retry = 2
|
||||
f.Enable()
|
||||
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, readTime)
|
||||
}
|
||||
|
||||
} else {
|
||||
f.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", f.Addr(), f.Priority(), p.config.CheckWebSite, buf)
|
||||
if checkWebSite(f, p.config.CheckWebSite, time.Duration(p.config.CheckTimeout)*time.Second, buf) {
|
||||
wait = 1
|
||||
continue
|
||||
}
|
||||
|
||||
rc.Close()
|
||||
if wait == 0 {
|
||||
wait = 1
|
||||
}
|
||||
|
||||
wait *= 2
|
||||
if wait > 16 {
|
||||
wait = 16
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []byte) bool {
|
||||
startTime := time.Now()
|
||||
|
||||
rc, err := fwdr.Dial("tcp", website)
|
||||
if err != nil {
|
||||
fwdr.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. error in dial: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, err)
|
||||
return false
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
_, err = rc.Write([]byte("GET / HTTP/1.0\r\n\r\n"))
|
||||
if err != nil {
|
||||
fwdr.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. error in write: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, err)
|
||||
return false
|
||||
}
|
||||
|
||||
_, err = io.ReadFull(rc, buf)
|
||||
if err != nil {
|
||||
fwdr.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. error in read: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !bytes.Equal([]byte("HTTP"), buf) {
|
||||
fwdr.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. server response: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, buf)
|
||||
return false
|
||||
}
|
||||
|
||||
readTime := time.Since(startTime)
|
||||
fwdr.SetLatency(int64(readTime))
|
||||
|
||||
if readTime > timeout {
|
||||
fwdr.Disable()
|
||||
log.F("[check] %s(%d) -> %s, DISABLED. check timeout: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, readTime)
|
||||
return false
|
||||
}
|
||||
|
||||
fwdr.Enable()
|
||||
log.F("[check] %s(%d) -> %s, ENABLED. connect time: %s", fwdr.Addr(), fwdr.Priority(),
|
||||
website, readTime)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Round Robin
|
||||
func (p *Proxy) scheduleRR(dstAddr string) *Forwarder {
|
||||
return p.avail[atomic.AddUint32(&p.index, 1)%uint32(len(p.avail))]
|
||||
|
Loading…
Reference in New Issue
Block a user