mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 01:15:41 +08:00
check: support tcp check, use checktype & checkaddr instead of checkwebsite
This commit is contained in:
parent
e6e5c3d4b6
commit
1173f533ec
@ -44,7 +44,8 @@ func parseConfig() *Config {
|
||||
|
||||
flag.StringSliceUniqVar(&conf.Forwards, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]")
|
||||
flag.StringVar(&conf.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr")
|
||||
flag.StringVar(&conf.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
|
||||
flag.StringVar(&conf.StrategyConfig.CheckType, "checktype", "http", "fowarder check type, http/tcp, default: http")
|
||||
flag.StringVar(&conf.StrategyConfig.CheckAddr, "checkaddr", "www.apple.com:80", "fowarder check addr, format: HOST[:PORT], default port: 80,")
|
||||
flag.IntVar(&conf.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)")
|
||||
flag.IntVar(&conf.StrategyConfig.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)")
|
||||
flag.IntVar(&conf.StrategyConfig.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode")
|
||||
|
5
go.mod
5
go.mod
@ -14,8 +14,9 @@ require (
|
||||
github.com/nadoo/ipset v0.3.0
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/xtaci/kcp-go/v5 v5.6.1
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||
golang.org/x/tools v0.0.0-20201111224557-41a3a589386c // indirect
|
||||
golang.org/x/crypto v0.0.0-20201116153603-4be66e5b6582
|
||||
golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48 // indirect
|
||||
golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect
|
||||
)
|
||||
|
||||
|
13
go.sum
13
go.sum
@ -87,8 +87,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201116153603-4be66e5b6582 h1:0WDrJ1E7UolDk1KhTXxxw3Fc8qtk5x7dHP431KHEJls=
|
||||
golang.org/x/crypto v0.0.0-20201116153603-4be66e5b6582/go.mod h1:tCqSYrHVcf3i63Co2FzBkTCo2gdF6Zak62921dSfraU=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@ -119,6 +119,7 @@ golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -127,6 +128,10 @@ golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48 h1:AYCWBZhgIw6XobZ5CibNJr0Rc4ZofGGKvWa1vcx2IGk=
|
||||
golang.org/x/sys v0.0.0-20201116194326-cc9327a14d48/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201113234701-d7a72108b828 h1:htWEtQEuEVJ4tU/Ngx7Cd/4Q7e3A5Up1owgyBtVsTwk=
|
||||
golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -136,8 +141,8 @@ golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||
golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174 h1:0rx0F4EjJNbxTuzWe0KjKcIzs+3VEb/Mrs/d1ciNz1c=
|
||||
golang.org/x/tools v0.0.0-20201105001634-bc3cf281b174/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201111224557-41a3a589386c h1:o4Kpkl2kZqc7n22gkunVhOJ+Ys5u3NrnXKAr2OgO5s0=
|
||||
golang.org/x/tools v0.0.0-20201111224557-41a3a589386c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10 h1:epqY6OjPdDktZ8Cbnv7rUhy89e44hYWhxmhdecJr4cg=
|
||||
golang.org/x/tools v0.0.0-20201117021029-3c3a81204b10/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
2
main.go
2
main.go
@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "0.12.3"
|
||||
version = "0.13.0"
|
||||
config = parseConfig()
|
||||
)
|
||||
|
||||
|
@ -26,7 +26,8 @@ type Config struct {
|
||||
// StrategyConfig is config of strategy.
|
||||
type StrategyConfig struct {
|
||||
Strategy string
|
||||
CheckWebSite string
|
||||
CheckType string
|
||||
CheckAddr string
|
||||
CheckInterval int
|
||||
CheckTimeout int
|
||||
CheckTolerance int
|
||||
@ -44,7 +45,8 @@ func NewConfFromFile(ruleFile string) (*Config, error) {
|
||||
f := conflag.NewFromFile("rule", ruleFile)
|
||||
f.StringSliceUniqVar(&p.Forward, "forward", nil, "forward url, format: SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS[,SCHEME://[USER|METHOD:PASSWORD@][HOST]:PORT?PARAMS]")
|
||||
f.StringVar(&p.StrategyConfig.Strategy, "strategy", "rr", "forward strategy, default: rr")
|
||||
f.StringVar(&p.StrategyConfig.CheckWebSite, "checkwebsite", "www.apple.com", "fowarder check HTTP(NOT HTTPS) website address, format: HOST[:PORT], default port: 80")
|
||||
f.StringVar(&p.StrategyConfig.CheckType, "checktype", "http", "fowarder check type, http/tcp, default: http")
|
||||
f.StringVar(&p.StrategyConfig.CheckAddr, "checkaddr", "www.apple.com:80", "fowarder check addr, format: HOST[:PORT], default port: 80,")
|
||||
f.IntVar(&p.StrategyConfig.CheckInterval, "checkinterval", 30, "fowarder check interval(seconds)")
|
||||
f.IntVar(&p.StrategyConfig.CheckTimeout, "checktimeout", 10, "fowarder check timeout(seconds)")
|
||||
f.IntVar(&p.StrategyConfig.CheckTolerance, "checktolerance", 0, "fowarder check tolerance(ms), switch only when new_latency < old_latency - tolerance, only used in lha mode")
|
||||
|
@ -63,8 +63,8 @@ func newFwdrGroup(name string, fwdrs []*Forwarder, c *StrategyConfig) *FwdrGroup
|
||||
|
||||
p.init()
|
||||
|
||||
if strings.IndexByte(p.config.CheckWebSite, ':') == -1 {
|
||||
p.config.CheckWebSite += ":80"
|
||||
if strings.IndexByte(p.config.CheckAddr, ':') == -1 {
|
||||
p.config.CheckAddr += ":80"
|
||||
}
|
||||
|
||||
// default scheduler
|
||||
@ -180,15 +180,20 @@ func (p *FwdrGroup) onStatusChanged(fwdr *Forwarder) {
|
||||
|
||||
// Check implements the Checker interface.
|
||||
func (p *FwdrGroup) Check() {
|
||||
if p.config.CheckType != "http" && p.config.CheckType != "tcp" {
|
||||
p.config.MaxFailures = 0
|
||||
return
|
||||
}
|
||||
|
||||
// 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(p.fwdrs[i])
|
||||
go p.check(p.fwdrs[i], p.config.CheckType == "http")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *FwdrGroup) check(f *Forwarder) {
|
||||
func (p *FwdrGroup) check(f *Forwarder, http bool) {
|
||||
wait := uint8(0)
|
||||
buf := make([]byte, 4)
|
||||
intval := time.Duration(p.config.CheckInterval) * time.Second
|
||||
@ -205,9 +210,16 @@ func (p *FwdrGroup) check(f *Forwarder) {
|
||||
continue
|
||||
}
|
||||
|
||||
if checkWebSite(f, p.config.CheckWebSite, time.Duration(p.config.CheckTimeout)*time.Second, buf) {
|
||||
wait = 1
|
||||
continue
|
||||
if http {
|
||||
if checkHttp(f, p.config.CheckAddr, time.Duration(p.config.CheckTimeout)*time.Second, buf) {
|
||||
wait = 1
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if checkTcp(f, p.config.CheckAddr, time.Duration(p.config.CheckTimeout)*time.Second) {
|
||||
wait = 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if wait == 0 {
|
||||
@ -221,12 +233,12 @@ func (p *FwdrGroup) check(f *Forwarder) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []byte) bool {
|
||||
func checkTcp(fwdr *Forwarder, addr string, timeout time.Duration) bool {
|
||||
startTime := time.Now()
|
||||
|
||||
rc, err := fwdr.Dial("tcp", website)
|
||||
rc, err := fwdr.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(), website, err)
|
||||
log.F("[check-tcp] %s(%d), FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(), err)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
@ -236,36 +248,66 @@ func checkWebSite(fwdr *Forwarder, website string, timeout time.Duration, buf []
|
||||
rc.SetDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
_, err = io.WriteString(rc, "GET / HTTP/1.1\r\nHost:"+website+"\r\nConnection: close"+"\r\n\r\n")
|
||||
elapsed := time.Since(startTime)
|
||||
fwdr.SetLatency(int64(elapsed))
|
||||
|
||||
if elapsed > timeout {
|
||||
log.F("[check-tcp] %s(%d), FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(), elapsed)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
|
||||
log.F("[check-tcp] %s(%d), SUCCESS. elapsed: %s", fwdr.Addr(), fwdr.Priority(), elapsed)
|
||||
fwdr.Enable()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func checkHttp(fwdr *Forwarder, addr string, timeout time.Duration, buf []byte) bool {
|
||||
startTime := time.Now()
|
||||
|
||||
rc, err := fwdr.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in write: %s", fwdr.Addr(), fwdr.Priority(), website, err)
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in dial: %s", fwdr.Addr(), fwdr.Priority(), addr, err)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
if timeout > 0 {
|
||||
rc.SetDeadline(time.Now().Add(timeout))
|
||||
}
|
||||
|
||||
_, err = io.WriteString(rc, "GET / HTTP/1.1\r\nHost:"+addr+"\r\nConnection: close"+"\r\n\r\n")
|
||||
if err != nil {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in write: %s", fwdr.Addr(), fwdr.Priority(), addr, err)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
|
||||
_, err = io.ReadFull(rc, buf)
|
||||
if err != nil {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in read: %s", fwdr.Addr(), fwdr.Priority(), website, err)
|
||||
log.F("[check] %s(%d) -> %s, FAILED. error in read: %s", fwdr.Addr(), fwdr.Priority(), addr, err)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
|
||||
if !bytes.Equal([]byte("HTTP"), buf) {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. server response: %s", fwdr.Addr(), fwdr.Priority(), website, buf)
|
||||
log.F("[check] %s(%d) -> %s, FAILED. server response: %s", fwdr.Addr(), fwdr.Priority(), addr, buf)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
|
||||
readTime := time.Since(startTime)
|
||||
fwdr.SetLatency(int64(readTime))
|
||||
elapsed := time.Since(startTime)
|
||||
fwdr.SetLatency(int64(elapsed))
|
||||
|
||||
if readTime > timeout {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(), website, readTime)
|
||||
if elapsed > timeout {
|
||||
log.F("[check] %s(%d) -> %s, FAILED. check timeout: %s", fwdr.Addr(), fwdr.Priority(), addr, elapsed)
|
||||
fwdr.Disable()
|
||||
return false
|
||||
}
|
||||
|
||||
log.F("[check] %s(%d) -> %s, SUCCESS. elapsed time: %s", fwdr.Addr(), fwdr.Priority(), website, readTime)
|
||||
log.F("[check] %s(%d) -> %s, SUCCESS. elapsed: %s", fwdr.Addr(), fwdr.Priority(), addr, elapsed)
|
||||
fwdr.Enable()
|
||||
|
||||
return true
|
||||
|
Loading…
Reference in New Issue
Block a user