Skip to content

Commit

Permalink
support least connections (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiuker committed Dec 13, 2023
1 parent 7c42b1e commit 2cf91ba
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/vulncheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ 1.21.4 ]
go-version: [ 1.21.5 ]
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v3
Expand Down
53 changes: 46 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ var (
globalStatusCodes []int
globalConnStats []*ConnStats
log2 *logrus.Logger
globalHostBalance string
)

const (
Expand Down Expand Up @@ -183,6 +184,8 @@ func (b *Backend) getServerStatus() string {

// BackendStats holds server stats for backend
type BackendStats struct {
LastFinished atomic.Int64
CurrentCalls atomic.Int64
sync.Mutex
LastDowntime time.Duration
CumDowntime time.Duration
Expand Down Expand Up @@ -445,20 +448,44 @@ func (s *site) upBackends() []*Backend {
}

// Returns the next backend the request should go to.
func (s *site) nextProxy() *Backend {
func (s *site) nextProxy() (*Backend, func()) {
backends := s.upBackends()
if len(backends) == 0 {
return nil
return nil, func() {}
}
switch globalHostBalance {
case "least":
min := int64(math.MaxInt32)
earliest := time.Now().Add(time.Second).UnixNano()
idx := 0
for i, backend := range backends {
currentCalls := backend.Stats.CurrentCalls.Load()
if currentCalls < min {
min = currentCalls
lastFinished := backend.Stats.LastFinished.Load()
if lastFinished < earliest {
earliest = lastFinished
idx = i
}
}
}
backend := backends[idx]
backend.Stats.CurrentCalls.Add(1)
return backend, func() {
backend.Stats.CurrentCalls.Add(-1)
backend.Stats.LastFinished.Store(time.Now().UnixNano())
}
default:
idx := rand.Intn(len(backends))
// random backend from a list of available backends.
return backends[idx], func() {}
}

idx := rand.Intn(len(backends))
// random backend from a list of available backends.
return backends[idx]
}

// ServeHTTP - LoadBalancer implements http.Handler
func (s *site) ServeHTTP(w http.ResponseWriter, r *http.Request) {
backend := s.nextProxy()
backend, done := s.nextProxy()
defer done()
if backend != nil && backend.Online() {
httpTraceHdrs(backend.proxy.ServeHTTP, w, r, backend)
return
Expand Down Expand Up @@ -811,6 +838,10 @@ func sidekickMain(ctx *cli.Context) {
globalDebugEnabled = ctx.GlobalBool("debug")
globalErrorsOnly = ctx.GlobalBool("errors")
globalStatusCodes = ctx.GlobalIntSlice("status-code")
globalHostBalance = ctx.GlobalString("host-balance")
if globalHostBalance == "" {
globalHostBalance = "least"
}

go func() {
t := time.NewTicker(ctx.GlobalDuration("dns-ttl"))
Expand Down Expand Up @@ -973,6 +1004,11 @@ func main() {
Name: "status-code",
Usage: "filter by given status code",
},
cli.StringFlag{
Name: "host-balance",
Usage: "specify the algorithm to select backend host when load balancing, supported values are 'least', 'random'",
Value: "least",
},
}
app.CustomAppHelpTemplate = `NAME:
{{.Name}} - {{.Description}}
Expand Down Expand Up @@ -1007,6 +1043,9 @@ EXAMPLES:
6. Sidekick as TLS terminator:
$ sidekick --cert public.crt --key private.key --health-path=/minio/health/cluster http://site1-minio{1...4}:9000
7. Load balance across 4 MinIO Servers (http://minio1:9000 to http://minio4:9000), Set host balance as least
$ sidekick --host-balance=least --health-path=/minio/health/cluster http://minio{1...4}:9000
`
app.Action = sidekickMain
app.Run(os.Args)
Expand Down

0 comments on commit 2cf91ba

Please sign in to comment.