mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-25 10:18:59 +02:00
migrated from logrus to zerolog, improved error formatting, fixed concurrent map write, fixed crash on rapid page refresh for idle containers, fixed infinite recursion on gotfiy error, fixed websocket connection problem when using idlewatcher
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
package loadbalancer
|
||||
|
||||
import "net/http"
|
||||
|
||||
type DummyResponseWriter struct{}
|
||||
|
||||
func (w *DummyResponseWriter) Header() (_ http.Header) {
|
||||
return
|
||||
}
|
||||
|
||||
func (w *DummyResponseWriter) Write([]byte) (_ int, _ error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (w *DummyResponseWriter) WriteHeader(int) {}
|
||||
@@ -11,20 +11,22 @@ import (
|
||||
)
|
||||
|
||||
type ipHash struct {
|
||||
*LoadBalancer
|
||||
|
||||
realIP *middleware.Middleware
|
||||
pool servers
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (lb *LoadBalancer) newIPHash() impl {
|
||||
impl := new(ipHash)
|
||||
impl := &ipHash{LoadBalancer: lb}
|
||||
if len(lb.Options) == 0 {
|
||||
return impl
|
||||
}
|
||||
var err E.Error
|
||||
impl.realIP, err = middleware.NewRealIP(lb.Options)
|
||||
if err != nil {
|
||||
logger.Errorf("loadbalancer %s invalid real_ip options: %s, ignoring", lb.Link, err)
|
||||
E.LogError("invalid real_ip options, ignoring", err, &impl.Logger)
|
||||
}
|
||||
return impl
|
||||
}
|
||||
@@ -70,7 +72,7 @@ func (impl *ipHash) serveHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
ip, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
http.Error(rw, "Internal error", http.StatusInternalServerError)
|
||||
logger.Errorf("invalid remote address %s: %s", r.RemoteAddr, err)
|
||||
impl.Err(err).Msg("invalid remote address " + r.RemoteAddr)
|
||||
return
|
||||
}
|
||||
idx := hashIP(ip) % uint32(len(impl.pool))
|
||||
|
||||
@@ -31,14 +31,14 @@ func (impl *leastConn) ServeHTTP(srvs servers, rw http.ResponseWriter, r *http.R
|
||||
srv := srvs[0]
|
||||
minConn, ok := impl.nConn.Load(srv)
|
||||
if !ok {
|
||||
logger.Errorf("[BUG] server %s not found", srv.Name)
|
||||
impl.Error().Msgf("[BUG] server %s not found", srv.Name)
|
||||
http.Error(rw, "Internal error", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
for i := 1; i < len(srvs); i++ {
|
||||
nConn, ok := impl.nConn.Load(srvs[i])
|
||||
if !ok {
|
||||
logger.Errorf("[BUG] server %s not found", srv.Name)
|
||||
impl.Error().Msgf("[BUG] server %s not found", srv.Name)
|
||||
http.Error(rw, "Internal error", http.StatusInternalServerError)
|
||||
}
|
||||
if nConn.Load() < minConn.Load() {
|
||||
|
||||
@@ -6,9 +6,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
idlewatcher "github.com/yusing/go-proxy/internal/docker/idlewatcher/types"
|
||||
E "github.com/yusing/go-proxy/internal/error"
|
||||
gphttp "github.com/yusing/go-proxy/internal/net/http"
|
||||
"github.com/yusing/go-proxy/internal/net/http/middleware"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
"github.com/yusing/go-proxy/internal/watcher/health"
|
||||
@@ -29,6 +31,8 @@ type (
|
||||
Options middleware.OptionsRaw `json:"options,omitempty" yaml:"options,omitempty"`
|
||||
}
|
||||
LoadBalancer struct {
|
||||
zerolog.Logger
|
||||
|
||||
impl
|
||||
*Config
|
||||
|
||||
@@ -48,6 +52,7 @@ const maxWeight weightType = 100
|
||||
|
||||
func New(cfg *Config) *LoadBalancer {
|
||||
lb := &LoadBalancer{
|
||||
Logger: logger.With().Str("name", cfg.Link).Logger(),
|
||||
Config: new(Config),
|
||||
pool: newPool(),
|
||||
task: task.DummyTask(),
|
||||
@@ -102,7 +107,7 @@ func (lb *LoadBalancer) UpdateConfigIfNeeded(cfg *Config) {
|
||||
if lb.Mode == Unset && cfg.Mode != Unset {
|
||||
lb.Mode = cfg.Mode
|
||||
if !lb.Mode.ValidateUpdate() {
|
||||
logger.Warnf("loadbalancer %s: invalid mode %q, fallback to %q", cfg.Link, cfg.Mode, lb.Mode)
|
||||
lb.Error().Msgf("invalid mode %q, fallback to %q", cfg.Mode, lb.Mode)
|
||||
}
|
||||
lb.updateImpl()
|
||||
}
|
||||
@@ -131,7 +136,11 @@ func (lb *LoadBalancer) AddServer(srv *Server) {
|
||||
|
||||
lb.rebalance()
|
||||
lb.impl.OnAddServer(srv)
|
||||
logger.Debugf("[add] %s to loadbalancer %s: %d servers available", srv.Name, lb.Link, lb.pool.Size())
|
||||
|
||||
lb.Debug().
|
||||
Str("action", "add").
|
||||
Str("server", srv.Name).
|
||||
Msgf("%d servers available", lb.pool.Size())
|
||||
}
|
||||
|
||||
func (lb *LoadBalancer) RemoveServer(srv *Server) {
|
||||
@@ -148,13 +157,15 @@ func (lb *LoadBalancer) RemoveServer(srv *Server) {
|
||||
lb.rebalance()
|
||||
lb.impl.OnRemoveServer(srv)
|
||||
|
||||
lb.Debug().
|
||||
Str("action", "remove").
|
||||
Str("server", srv.Name).
|
||||
Msgf("%d servers left", lb.pool.Size())
|
||||
|
||||
if lb.pool.Size() == 0 {
|
||||
lb.task.Finish("no server left")
|
||||
logger.Infof("loadbalancer %s stopped", lb.Link)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debugf("[remove] %s from loadbalancer %s: %d servers left", srv.Name, lb.Link, lb.pool.Size())
|
||||
}
|
||||
|
||||
func (lb *LoadBalancer) rebalance() {
|
||||
@@ -218,7 +229,7 @@ func (lb *LoadBalancer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
|
||||
defer cancel()
|
||||
// send dummy request to wake all servers
|
||||
var dummyRW *DummyResponseWriter
|
||||
var dummyRW gphttp.DummyResponseWriter
|
||||
for _, srv := range srvs {
|
||||
// wake only if server implements Waker
|
||||
_, ok := srv.handler.(idlewatcher.Waker)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package loadbalancer
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
import "github.com/yusing/go-proxy/internal/logging"
|
||||
|
||||
var logger = logrus.WithField("module", "load_balancer")
|
||||
var logger = logging.With().Str("module", "load_balancer").Logger()
|
||||
|
||||
Reference in New Issue
Block a user