Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini-lb

Small HTTP reverse-proxy load balancer. Round-robin or least-connections, active health checks, retry on backend failure, and a JSON status endpoint. Standard library only.

Run

./mini-lb \
  --listen          :8080 \
  --backends        http://api-a:9000,http://api-b:9000,http://api-c:9000 \
  --strategy        least-connections \
  --health-path     /healthz \
  --max-retries     2 \
  --verbose

Status endpoint

$ curl -s localhost:8080/_lb/status | jq .
{
  "strategy": "least-connections",
  "backends": [
    { "url": "http://api-a:9000", "alive": true,  "active_conns": 3, "total_served": 1204, "total_errored": 2 },
    { "url": "http://api-b:9000", "alive": false, "active_conns": 0, "total_served": 812,  "total_errored": 17 }
  ]
}

Retrying safely

Retrying a failed request only works if nothing has been sent to the client yet. If the upstream dies after the response has already started streaming, you can't just switch backends — you'd write a second set of headers on top of a half-sent body.

So each proxy call is wrapped in a writer that records whether WriteHeader has fired. Errors before that point are retried on the next healthy backend; errors after it let the request finish as-is.

if pe.err != nil {
    lb.pool.MarkDown(b)
    if wrapped.wroteHeader {
        return true   // already streaming, can't retry
    }
    return false      // safe to try another backend
}

Health checks

A goroutine probes health-path on every backend at health-interval. Anything >= 500 or a network error marks it down; the next good probe brings it back.

Build

go build -o mini-lb .

Flags

--listen           listen address                    (default :8080)
--backends         comma-separated backend URLs      (required)
--strategy         round-robin | least-connections   (default round-robin)
--health-path      health probe path                 (default /healthz)
--health-interval  probe interval                    (default 5s)
--health-timeout   probe timeout                     (default 2s)
--max-retries      retries on failure                (default 2)
--verbose          debug logging

Layout

  • pool — backends + health-check loop
  • strategy — Strategy interface, round-robin, least-connections
  • main — flags, dispatch, status endpoint, shutdown

About

Compact HTTP load balancer in Go with active health checks and automatic failover. No external dependencies.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages