Files
fn-serverless/lb/lb.go
Seif Lotfy سيف لطفي ee398f0d7d Add initial load balancer (#487)
* lb: library for creation of load balancer

* lb: library for creation of load balancer

* Add balance subcommand to fn

* make fnlb its own command

* Update Changelogg

* Add Makefile for fnlb
2017-01-19 03:11:39 +01:00

53 lines
1.3 KiB
Go

package lb
import (
"bytes"
"context"
"net/http"
"net/http/httputil"
"strconv"
"sync"
"sync/atomic"
"github.com/golang/groupcache/consistenthash"
)
// ConsistentHashReverseProxy returns a new ReverseProxy that routes
// URLs to the scheme, host, and base path provided in by a consistent hash
// algorithm. If the target's path is "/base" and the incoming request was for
// "/dir", the target request will be for /base/dir.
// ConsistentHashReverseProxy does not rewrite the Host header.
func ConsistentHashReverseProxy(ctx context.Context, nodes []string) *httputil.ReverseProxy {
ch := consistenthash.New(len(nodes), nil)
ch.Add(nodes...)
bufPool := sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
var i int64
director := func(req *http.Request) {
buf := bufPool.Get().(*bytes.Buffer)
defer bufPool.Put(buf)
buf.Reset()
buf.WriteString(req.URL.Path)
buf.WriteString("??")
b := strconv.AppendInt(buf.Bytes(), atomic.AddInt64(&i, 1), 10)
target := ch.Get(string(b))
req.URL.Scheme = "http"
req.URL.Host = target
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
}
return &httputil.ReverseProxy{
Director: director,
Transport: NewRoundTripper(ctx, nodes),
}
}