From af0028d821d334c23e913045f5e9ba6d317dbdfa Mon Sep 17 00:00:00 2001 From: Jelmer Snoeck Date: Fri, 1 Apr 2016 13:10:18 +0100 Subject: [PATCH] HTTPTransport: implement queue for listener. Before this patch, when an error occurs in trying to accept a connection from the listener, the error would be returned. This also happened on temporary issues like `too many open files`. Temporary issues are "self-healing" and will resolve over time. This means that we can put the requests in a queue to wait until the issue is resolved and start processing the connections once it is resolved. This patch implements such mechanism, as copied from the standard library http package. It will retry temporary errors but will return permanent errors (or errors that are not from the net.Error type). --- transport/http_transport.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/transport/http_transport.go b/transport/http_transport.go index 9d4105a5..c2c56c51 100644 --- a/transport/http_transport.go +++ b/transport/http_transport.go @@ -8,12 +8,14 @@ import ( "fmt" "io" "io/ioutil" + "log" "net" "net/http" "net/url" "strconv" "strings" "sync" + "time" mls "github.com/micro/misc/lib/tls" ) @@ -309,9 +311,23 @@ func (h *httpTransportListener) Close() error { } func (h *httpTransportListener) Accept(fn func(Socket)) error { + var tempDelay time.Duration for { c, err := h.listener.Accept() if err != nil { + if ne, ok := err.(net.Error); ok && ne.Temporary() { + if tempDelay == 0 { + tempDelay = 5 * time.Millisecond + } else { + tempDelay *= 2 + } + if max := 1 * time.Second; tempDelay > max { + tempDelay = max + } + log.Printf("http: Accept error: %v; retrying in %v\n", err, tempDelay) + time.Sleep(tempDelay) + continue + } return err }