proxy: Fix retry logic for when no hosts are available

This commit is contained in:
Matthew Holt 2016-09-24 16:30:40 -06:00
parent 0c0142c8cc
commit a661007a55
No known key found for this signature in database
GPG Key ID: 0D97CC73664F4D03
2 changed files with 20 additions and 11 deletions

View File

@ -94,17 +94,33 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
// outreq is the request that makes a roundtrip to the backend
outreq := createUpstreamRequest(r)
// since Select() should give us "up" hosts, keep retrying
// hosts until timeout (or until we get a nil host).
// The keepRetrying function will return true if we should
// loop and try to select another host, or false if we
// should break and stop retrying.
start := time.Now()
keepRetrying := func() bool {
// if we've tried long enough, break
if time.Now().Sub(start) >= upstream.GetTryDuration() {
return false
}
// otherwise, wait and try the next available host
time.Sleep(upstream.GetTryInterval())
return true
}
var backendErr error
for {
// since Select() should give us "up" hosts, keep retrying
// hosts until timeout (or until we get a nil host).
host := upstream.Select(r)
if host == nil {
if backendErr == nil {
backendErr = errors.New("no hosts available upstream")
}
return http.StatusBadGateway, backendErr
if !keepRetrying() {
break
}
continue
}
if rr, ok := w.(*httpserver.ResponseRecorder); ok && rr.Replacer != nil {
rr.Replacer.Set("upstream", host.Name)
@ -170,12 +186,9 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
}
// if we've tried long enough, break
if time.Now().Sub(start) >= upstream.GetTryDuration() {
if !keepRetrying() {
break
}
// otherwise, wait and try the next available host
time.Sleep(upstream.GetTryInterval())
}
return http.StatusBadGateway, backendErr

View File

@ -24,10 +24,6 @@ import (
"golang.org/x/net/websocket"
)
func init() {
tryDuration = 50 * time.Millisecond // prevent tests from hanging
}
func TestReverseProxy(t *testing.T) {
log.SetOutput(ioutil.Discard)
defer log.SetOutput(os.Stderr)