Navigator now supports unweighted and weighted load balancing.

This commit is contained in:
Yifu Yu 2019-12-26 01:10:26 +08:00
parent 22855ebec2
commit 6ac03c18cc
3 changed files with 76 additions and 11 deletions

View File

@ -4,11 +4,14 @@ import (
"flag" "flag"
"fmt" "fmt"
"log" "log"
"math/rand"
"os" "os"
"os/signal" "os/signal"
"sort"
"sync" "sync"
"sync/atomic" "sync/atomic"
"syscall" "syscall"
"time"
"go.starlark.net/starlark" "go.starlark.net/starlark"
) )
@ -36,6 +39,7 @@ var (
reloadSignal = make(chan os.Signal) reloadSignal = make(chan os.Signal)
pool *threadPool pool *threadPool
counter uint64 counter uint64
rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
) )
func newThreadPool(size int) *threadPool { func newThreadPool(size int) *threadPool {
@ -147,9 +151,56 @@ func GetMapping(ip string) string {
log.Println("Starlark execute error:", err.Error()) log.Println("Starlark execute error:", err.Error())
return "" return ""
} }
if r, ok := ret.(starlark.String); ok { switch r := ret.(type) {
case starlark.String:
return string(r) return string(r)
case *starlark.List:
val := r.Index(rnd.Intn(r.Len()))
if s, ok := val.(starlark.String); ok {
return string(s)
}
goto scriptError
case starlark.Tuple:
val := r.Index(rnd.Intn(r.Len()))
if s, ok := val.(starlark.String); ok {
return string(s)
}
goto scriptError
case *starlark.Dict:
values := r.Items()
options := make([]string, r.Len())
tot := int64(0)
for i := range values {
if v, ok := values[i].Index(0).(starlark.String); ok {
options[i] = string(v)
} else {
goto scriptError
}
if v, ok := values[i].Index(1).(starlark.Int); ok {
if weight, ok := v.Int64(); ok {
tot += weight
} else {
goto scriptError
}
} else {
goto scriptError
}
}
sort.Strings(options)
pos := rnd.Int63n(tot)
for _, option := range options {
w, _, _ := r.Get(starlark.String(option))
v, _ := w.(starlark.Int).Int64()
pos -= v
if pos < 0 {
return option
}
}
log.Println("Unexpected code execution,",
"check random logic for *starlark.Dict")
return options[len(options)-1]
} }
scriptError:
log.Println("Script returned unexpected result:", ret.String()) log.Println("Script returned unexpected result:", ret.String())
return "" return ""
} }

View File

@ -7,8 +7,7 @@ import (
var ( var (
defaultServer = flag.String("fallback-node", defaultServer = flag.String("fallback-node",
"xe-mci1-us.edge.eve.network", "xe-mci1-us", "Default CDN node in case of any script error")
"Default CDN node in case of any script error")
defaultSuffix = flag.String("fallback-suffix", defaultSuffix = flag.String("fallback-suffix",
".edge.eve.network", ".edge.eve.network",
"Default CDN suffix in case of any script error") "Default CDN suffix in case of any script error")
@ -19,11 +18,15 @@ func Initialize() {
} }
func Get(ip string) string { func Get(ip string) string {
ret := elf.GetMapping(ip) node := elf.GetMapping(ip)
if ret == "" { if node == "" {
return *defaultServer node = *defaultServer
} }
return ret suffix := elf.GetSuffix(ip)
if suffix == "" {
suffix = *defaultSuffix
}
return node + suffix
} }
func GetSuffix(ip string) string { func GetSuffix(ip string) string {

View File

@ -1,6 +1,9 @@
WHOLESALE_INTERNET_10GE = "xe-mci1-us" WHOLESALE_INTERNET_10GE = "xe-mci1-us"
HETZNER_FSN_1GE = "ge-fsn1-de" HETZNER_FSN_1GE = "ge-fsn1-de"
HETZNER_HEL_1GE = "ge-hel1-fi" HETZNER_HEL_1GE = "ge-hel1-fi"
CLOUDCONE_LAX1_1GE = "ge-lax1-us"
CLOUDCONE_LAX2_1GE = "ge-lax2-us"
CLOUDCONE_LAX_LB = (CLOUDCONE_LAX1_1GE, CLOUDCONE_LAX2_1GE)
default_server = WHOLESALE_INTERNET_10GE default_server = WHOLESALE_INTERNET_10GE
CHINA_MAINLAND_SUFFIX = ".eveedge.link" CHINA_MAINLAND_SUFFIX = ".eveedge.link"
@ -11,12 +14,20 @@ default_suffix = GLOBAL_SUFFIX
def getMapping(ip): def getMapping(ip):
info = geoLookup(ip) info = geoLookup(ip)
if not info: if not info:
return default_server + default_suffix return default_server
if info.IspDomain == "ChinaMobile": if info.IspDomain == "ChinaMobile":
return HETZNER_FSN_1GE + CHINA_MAINLAND_SUFFIX return HETZNER_FSN_1GE
if info.IspDomain == "ChinaTelecom":
return CLOUDCONE_LAX_LB
if info.CountryCode == "CN": if info.CountryCode == "CN":
return default_server + CHINA_MAINLAND_SUFFIX return default_server
return default_server + GLOBAL_SUFFIX if ip == "0.11.45.14":
return {
default_server: 3,
CLOUDCONE_LAX1_1GE: 2,
CLOUDCONE_LAX2_1GE: 1,
}
return default_server
def getNodes(): def getNodes():
return ["xe-mci1-us", "ge-fsn1-de", "ge-lax1-us"] return ["xe-mci1-us", "ge-fsn1-de", "ge-lax1-us"]