Feature: add interval url test for load-balance
This commit is contained in:
parent
d3b280a7e5
commit
18f885a92a
3 changed files with 57 additions and 8 deletions
|
@ -43,7 +43,9 @@ func (p *Proxy) Alive() bool {
|
||||||
|
|
||||||
func (p *Proxy) Dial(metadata *C.Metadata) (net.Conn, error) {
|
func (p *Proxy) Dial(metadata *C.Metadata) (net.Conn, error) {
|
||||||
conn, err := p.ProxyAdapter.Dial(metadata)
|
conn, err := p.ProxyAdapter.Dial(metadata)
|
||||||
p.alive = err == nil
|
if err != nil {
|
||||||
|
p.alive = false
|
||||||
|
}
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +91,7 @@ func (p *Proxy) MarshalJSON() ([]byte, error) {
|
||||||
// URLTest get the delay for the specified URL
|
// URLTest get the delay for the specified URL
|
||||||
func (p *Proxy) URLTest(url string) (t uint16, err error) {
|
func (p *Proxy) URLTest(url string) (t uint16, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
p.alive = err == nil
|
||||||
record := C.DelayHistory{Time: time.Now()}
|
record := C.DelayHistory{Time: time.Now()}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
record.Delay = t
|
record.Delay = t
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/murmur3"
|
"github.com/Dreamacro/clash/common/murmur3"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
|
@ -15,6 +17,9 @@ type LoadBalance struct {
|
||||||
*Base
|
*Base
|
||||||
proxies []C.Proxy
|
proxies []C.Proxy
|
||||||
maxRetry int
|
maxRetry int
|
||||||
|
rawURL string
|
||||||
|
interval time.Duration
|
||||||
|
done chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getKey(metadata *C.Metadata) string {
|
func getKey(metadata *C.Metadata) string {
|
||||||
|
@ -62,6 +67,38 @@ func (lb *LoadBalance) Dial(metadata *C.Metadata) (net.Conn, error) {
|
||||||
return lb.proxies[0].Dial(metadata)
|
return lb.proxies[0].Dial(metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (lb *LoadBalance) Destroy() {
|
||||||
|
lb.done <- struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *LoadBalance) validTest() {
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
wg.Add(len(lb.proxies))
|
||||||
|
|
||||||
|
for _, p := range lb.proxies {
|
||||||
|
go func(p C.Proxy) {
|
||||||
|
p.URLTest(lb.rawURL)
|
||||||
|
wg.Done()
|
||||||
|
}(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lb *LoadBalance) loop() {
|
||||||
|
tick := time.NewTicker(lb.interval)
|
||||||
|
go lb.validTest()
|
||||||
|
Loop:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-tick.C:
|
||||||
|
go lb.validTest()
|
||||||
|
case <-lb.done:
|
||||||
|
break Loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||||
var all []string
|
var all []string
|
||||||
for _, proxy := range lb.proxies {
|
for _, proxy := range lb.proxies {
|
||||||
|
@ -74,21 +111,30 @@ func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoadBalanceOption struct {
|
type LoadBalanceOption struct {
|
||||||
Name string `proxy:"name"`
|
Name string `proxy:"name"`
|
||||||
Proxies []string `proxy:"proxies"`
|
Proxies []string `proxy:"proxies"`
|
||||||
|
URL string `proxy:"url"`
|
||||||
|
Interval int `proxy:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLoadBalance(name string, proxies []C.Proxy) (*LoadBalance, error) {
|
func NewLoadBalance(option LoadBalanceOption, proxies []C.Proxy) (*LoadBalance, error) {
|
||||||
if len(proxies) == 0 {
|
if len(proxies) == 0 {
|
||||||
return nil, errors.New("Provide at least one proxy")
|
return nil, errors.New("Provide at least one proxy")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LoadBalance{
|
interval := time.Duration(option.Interval) * time.Second
|
||||||
|
|
||||||
|
lb := &LoadBalance{
|
||||||
Base: &Base{
|
Base: &Base{
|
||||||
name: name,
|
name: option.Name,
|
||||||
tp: C.LoadBalance,
|
tp: C.LoadBalance,
|
||||||
},
|
},
|
||||||
proxies: proxies,
|
proxies: proxies,
|
||||||
maxRetry: 3,
|
maxRetry: 3,
|
||||||
}, nil
|
rawURL: option.URL,
|
||||||
|
interval: interval,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
go lb.loop()
|
||||||
|
return lb, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,7 +302,7 @@ func parseProxies(cfg *rawConfig) (map[string]C.Proxy, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ProxyGroup %s: %s", groupName, err.Error())
|
return nil, fmt.Errorf("ProxyGroup %s: %s", groupName, err.Error())
|
||||||
}
|
}
|
||||||
group, err = adapters.NewLoadBalance(loadBalanceOption.Name, ps)
|
group, err = adapters.NewLoadBalance(*loadBalanceOption, ps)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Proxy %s: %s", groupName, err.Error())
|
return nil, fmt.Errorf("Proxy %s: %s", groupName, err.Error())
|
||||||
|
|
Loading…
Reference in a new issue