mirror of
https://github.com/umputun/reproxy.git
synced 2024-11-24 08:12:31 +02:00
add lb selector
This commit is contained in:
parent
0217410207
commit
282b4b268c
15
app/main.go
15
app/main.go
@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
@ -31,6 +32,7 @@ var opts struct {
|
||||
MaxSize string `short:"m" long:"max" env:"MAX_SIZE" default:"64K" description:"max request size"`
|
||||
GzipEnabled bool `short:"g" long:"gzip" env:"GZIP" description:"enable gz compression"`
|
||||
ProxyHeaders []string `short:"x" long:"header" env:"HEADER" description:"proxy headers" env-delim:","`
|
||||
LBType string `long:"lb-type" env:"LB_TYPE" description:"load balancer type" choice:"random" choice:"failover" default:"random"` //nolint
|
||||
|
||||
SSL struct {
|
||||
Type string `long:"type" env:"TYPE" description:"ssl (auto) support" choice:"none" choice:"static" choice:"auto" default:"none"` //nolint
|
||||
@ -239,6 +241,7 @@ func run() error {
|
||||
AccessLog: accessLog,
|
||||
StdOutEnabled: opts.Logger.StdOut,
|
||||
Signature: opts.Signature,
|
||||
LBSelector: makeLBSelector(),
|
||||
Timeouts: proxy.Timeouts{
|
||||
ReadHeader: opts.Timeouts.ReadHeader,
|
||||
Write: opts.Timeouts.Write,
|
||||
@ -308,6 +311,18 @@ func makeProviders() ([]discovery.Provider, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func makeLBSelector() func(len int) int {
|
||||
switch opts.LBType {
|
||||
case "random":
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
return rand.Intn
|
||||
case "failover":
|
||||
return func(int) int { return 0 } // dead server won't be in the list, we can safely pick the first one
|
||||
default:
|
||||
return func(int) int { return 0 }
|
||||
}
|
||||
}
|
||||
|
||||
func makeSSLConfig() (config proxy.SSLConfig, err error) {
|
||||
switch opts.SSL.Type {
|
||||
case "none":
|
||||
|
@ -41,6 +41,7 @@ type Http struct { // nolint golint
|
||||
CacheControl MiddlewareProvider
|
||||
Metrics MiddlewareProvider
|
||||
Reporter Reporter
|
||||
LBSelector func(len int) int
|
||||
}
|
||||
|
||||
// Matcher source info (server and route) to the destination url
|
||||
@ -84,6 +85,10 @@ func (h *Http) Run(ctx context.Context) error {
|
||||
log.Printf("[DEBUG] assets file server enabled for %s, webroot %s", h.AssetsLocation, h.AssetsWebRoot)
|
||||
}
|
||||
|
||||
if h.LBSelector == nil {
|
||||
h.LBSelector = rand.Intn
|
||||
}
|
||||
|
||||
var httpServer, httpsServer *http.Server
|
||||
|
||||
go func() {
|
||||
@ -113,8 +118,6 @@ func (h *Http) Run(ctx context.Context) error {
|
||||
h.gzipHandler(),
|
||||
)
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
if len(h.SSLConfig.FQDNs) == 0 && h.SSLConfig.SSLMode == SSLAuto {
|
||||
// discovery async and may happen not right away. Try to get servers for some time
|
||||
for i := 0; i < 100; i++ {
|
||||
@ -206,8 +209,8 @@ func (h *Http) proxyHandler() http.HandlerFunc {
|
||||
server = strings.Split(r.Host, ":")[0]
|
||||
}
|
||||
matches := h.Match(server, r.URL.Path) // get all matches for the server:path pair
|
||||
u, ok := h.getMatch(matches, rand.Intn)
|
||||
if !ok { // no route match
|
||||
u, ok := h.getMatch(matches) // pick a single match from alive only, uses LBSelector as the strategy
|
||||
if !ok { // no route match
|
||||
if h.isAssetRequest(r) {
|
||||
assetsHandler.ServeHTTP(w, r)
|
||||
return
|
||||
@ -244,24 +247,25 @@ func (h *Http) proxyHandler() http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Http) getMatch(mm discovery.Matches, picker func(len int) int) (u string, ok bool) {
|
||||
func (h *Http) getMatch(mm discovery.Matches) (u string, ok bool) {
|
||||
if len(mm.Routes) == 0 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
var urls []string
|
||||
var urls []string // alive destinations only
|
||||
for _, m := range mm.Routes {
|
||||
if m.Alive {
|
||||
urls = append(urls, m.Destination)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(urls) {
|
||||
case 0:
|
||||
return "", false
|
||||
case 1:
|
||||
return urls[0], true
|
||||
default:
|
||||
return urls[picker(len(urls))], true
|
||||
return urls[h.LBSelector(len(urls))], true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,10 +408,10 @@ func TestHttp_getMatch(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
h := Http{}
|
||||
h := Http{LBSelector: func(len int) int { return 0 }}
|
||||
for i, tt := range tbl {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
res, ok := h.getMatch(tt.matches, func(len int) int { return 0 })
|
||||
res, ok := h.getMatch(tt.matches)
|
||||
require.Equal(t, tt.ok, ok)
|
||||
assert.Equal(t, tt.res, res)
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user