Commit a661007a authored by Matthew Holt's avatar Matthew Holt

proxy: Fix retry logic for when no hosts are available

parent 0c0142c8
...@@ -94,17 +94,33 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { ...@@ -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 is the request that makes a roundtrip to the backend
outreq := createUpstreamRequest(r) outreq := createUpstreamRequest(r)
// since Select() should give us "up" hosts, keep retrying // The keepRetrying function will return true if we should
// hosts until timeout (or until we get a nil host). // loop and try to select another host, or false if we
// should break and stop retrying.
start := time.Now() 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 var backendErr error
for { for {
// since Select() should give us "up" hosts, keep retrying
// hosts until timeout (or until we get a nil host).
host := upstream.Select(r) host := upstream.Select(r)
if host == nil { if host == nil {
if backendErr == nil { if backendErr == nil {
backendErr = errors.New("no hosts available upstream") 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 { if rr, ok := w.(*httpserver.ResponseRecorder); ok && rr.Replacer != nil {
rr.Replacer.Set("upstream", host.Name) rr.Replacer.Set("upstream", host.Name)
...@@ -170,12 +186,9 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { ...@@ -170,12 +186,9 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
} }
// if we've tried long enough, break // if we've tried long enough, break
if time.Now().Sub(start) >= upstream.GetTryDuration() { if !keepRetrying() {
break break
} }
// otherwise, wait and try the next available host
time.Sleep(upstream.GetTryInterval())
} }
return http.StatusBadGateway, backendErr return http.StatusBadGateway, backendErr
......
...@@ -24,10 +24,6 @@ import ( ...@@ -24,10 +24,6 @@ import (
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
func init() {
tryDuration = 50 * time.Millisecond // prevent tests from hanging
}
func TestReverseProxy(t *testing.T) { func TestReverseProxy(t *testing.T) {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
defer log.SetOutput(os.Stderr) defer log.SetOutput(os.Stderr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment