From 860b78dcfaba612be2e113e7172dda82919fb293 Mon Sep 17 00:00:00 2001 From: Shardul Nalegave Date: Tue, 20 Feb 2024 19:25:52 +0530 Subject: [PATCH] A minor refactor (removed all logging for now) --- balancer/balancer.go | 29 ----------------------------- freighter.go | 38 ++++++++++++++++++++------------------ go.mod | 11 +---------- go.sum | 32 -------------------------------- health.go | 2 -- pool/backend.go | 11 +++++++---- pool/pool.go | 2 ++ strategy/roundRobin.go | 1 + test/main.go | 31 +++++++++++++++++++++++++++++++ 9 files changed, 62 insertions(+), 95 deletions(-) delete mode 100644 balancer/balancer.go create mode 100644 test/main.go diff --git a/balancer/balancer.go b/balancer/balancer.go deleted file mode 100644 index cd0301f..0000000 --- a/balancer/balancer.go +++ /dev/null @@ -1,29 +0,0 @@ -package balancer - -import ( - "net/http" - "net/url" - "sync" - - "github.com/ShardulNalegave/freighter/pool" - "github.com/ShardulNalegave/freighter/strategy" - "github.com/rs/zerolog/log" -) - -type Balancer struct { - URL *url.URL - Pool *pool.ServerPool - Strategy strategy.Strategy -} - -func (b *Balancer) Handle(w http.ResponseWriter, r *http.Request) { - if srv := b.Strategy.Handle(r, b.Pool); srv != nil { - srv.ReverseProxy.ServeHTTP(w, r) - } -} - -func (b *Balancer) ListenAndServe(wg *sync.WaitGroup) { - defer wg.Done() - log.Info().Str("URL", b.URL.Host).Msg("Listening...") - http.ListenAndServe(b.URL.Host, http.HandlerFunc(b.Handle)) -} diff --git a/freighter.go b/freighter.go index 96efbb3..ff03bba 100644 --- a/freighter.go +++ b/freighter.go @@ -1,11 +1,11 @@ package freighter import ( + "net/http" "net/url" "sync" "time" - "github.com/ShardulNalegave/freighter/balancer" "github.com/ShardulNalegave/freighter/pool" "github.com/ShardulNalegave/freighter/strategy" ) @@ -18,33 +18,35 @@ type Options struct { } type Freighter struct { - p *pool.ServerPool - b *balancer.Balancer + URL *url.URL + pl *pool.ServerPool + Strategy strategy.Strategy healthCheckInterval time.Duration } -func (f *Freighter) ListenAndServe() { - var wg sync.WaitGroup - wg.Add(1) - go f.b.ListenAndServe(&wg) - go HealthCheck(f.p, f.healthCheckInterval) - wg.Wait() +func (f *Freighter) ListenAndServe(wg *sync.WaitGroup) { + defer wg.Done() + go HealthCheck(f.pl, f.healthCheckInterval) + http.ListenAndServe(f.URL.Host, http.HandlerFunc(f.Handle)) } -func NewFreighter(opts *Options) *Freighter { - p := &pool.ServerPool{ - Backends: opts.Backends, +func (f *Freighter) Handle(w http.ResponseWriter, r *http.Request) { + if backend := f.Strategy.Handle(r, f.pl); backend != nil { + backend.ReverseProxy.ServeHTTP(w, r) + } else { + http.Error(w, "Service unavailable", http.StatusServiceUnavailable) } +} - b := &balancer.Balancer{ - URL: opts.URL, - Pool: p, - Strategy: opts.Strategy, +func NewFreighter(opts *Options) *Freighter { + pl := &pool.ServerPool{ + Backends: opts.Backends, } return &Freighter{ - p: p, - b: b, + URL: opts.URL, + Strategy: opts.Strategy, + pl: pl, healthCheckInterval: opts.HealthCheckInterval, } } diff --git a/go.mod b/go.mod index ecbf896..685b860 100644 --- a/go.mod +++ b/go.mod @@ -2,13 +2,4 @@ module github.com/ShardulNalegave/freighter go 1.21.6 -require ( - github.com/google/uuid v1.6.0 - github.com/rs/zerolog v1.32.0 -) - -require ( - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/sys v0.17.0 // indirect -) +require github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum index 9d6076e..7790d7c 100644 --- a/go.sum +++ b/go.sum @@ -1,34 +1,2 @@ -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/health.go b/health.go index 82944a6..6211646 100644 --- a/health.go +++ b/health.go @@ -4,13 +4,11 @@ import ( "time" "github.com/ShardulNalegave/freighter/pool" - "github.com/rs/zerolog/log" ) func HealthCheck(p *pool.ServerPool, interval time.Duration) { t := time.NewTicker(interval) for range t.C { - log.Info().Msg("Running periodic Health-Check") p.CheckHealth() } } diff --git a/pool/backend.go b/pool/backend.go index 7df740d..194b4e8 100644 --- a/pool/backend.go +++ b/pool/backend.go @@ -8,18 +8,19 @@ import ( "time" "github.com/google/uuid" - "github.com/rs/zerolog/log" ) +// Backend is representation of an actual running backend. type Backend struct { ID string - Metadata map[string]interface{} + Metadata interface{} // Metadata to be set by user URL *url.URL alive bool mutex sync.RWMutex ReverseProxy *httputil.ReverseProxy } +// Returns the alive status of backend func (b *Backend) IsAlive() bool { b.mutex.RLock() alive := b.alive @@ -27,17 +28,18 @@ func (b *Backend) IsAlive() bool { return alive } +// Sets the alive status of backend func (b *Backend) SetAlive(alive bool) { b.mutex.Lock() b.alive = alive b.mutex.Unlock() } +// Checks backend health and update alive status accordingly func (b *Backend) CheckHealth() { timeout := 2 * time.Second conn, err := net.DialTimeout("tcp", b.URL.Host, timeout) if err != nil { - log.Error().Str("URL", b.URL.Host).Msg("Backend not responding") b.SetAlive(false) return } @@ -46,11 +48,12 @@ func (b *Backend) CheckHealth() { b.SetAlive(true) } +// Constructs a new backend instance func NewBackend(URL *url.URL, meta interface{}) *Backend { rp := httputil.NewSingleHostReverseProxy(URL) return &Backend{ ID: uuid.NewString(), - Metadata: make(map[string]interface{}), + Metadata: meta, URL: URL, ReverseProxy: rp, alive: true, diff --git a/pool/pool.go b/pool/pool.go index ee25e40..6cb1b71 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -1,9 +1,11 @@ package pool +// Server-Pool of all registered backends type ServerPool struct { Backends []*Backend } +// Checks health of all backends func (sp *ServerPool) CheckHealth() { for _, b := range sp.Backends { b.CheckHealth() diff --git a/strategy/roundRobin.go b/strategy/roundRobin.go index 478dc86..30d5ef5 100644 --- a/strategy/roundRobin.go +++ b/strategy/roundRobin.go @@ -23,6 +23,7 @@ func (rr *RoundRobin) Handle(r *http.Request, p *pool.ServerPool) *pool.Backend return p.Backends[index] } } + return nil } diff --git a/test/main.go b/test/main.go new file mode 100644 index 0000000..7d59d73 --- /dev/null +++ b/test/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "net/url" + "sync" + "time" + + "github.com/ShardulNalegave/freighter" + "github.com/ShardulNalegave/freighter/pool" + "github.com/ShardulNalegave/freighter/strategy" +) + +func main() { + srv := freighter.NewFreighter(&freighter.Options{ + URL: &url.URL{ + Host: ":5000", + }, + HealthCheckInterval: time.Second * 5, + Strategy: &strategy.RoundRobin{}, + Backends: []*pool.Backend{ + pool.NewBackend(&url.URL{Host: ":8080", Scheme: "http"}, nil), + }, + }) + + var wg sync.WaitGroup + wg.Add(1) + + go srv.ListenAndServe(&wg) + + wg.Wait() +}