mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* 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
53 lines
1.3 KiB
Go
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),
|
|
}
|
|
}
|