httpgoconnection

Creating an idle timeout in Go?


I use CloudFlare for one of my high volume websites, and it sits in front of my stack.

The thing is CloudFlare leaves idle connections open in addition to creating new ones, and it's not a setting I can change.

When I have Varnish or Nginx sitting in front listening on port 80 they have out of the box configuration to hang up the idle connections.

This is fine until I had to add a proxy written in Go to the front of my stack. It uses the net/http standard library.

I'm not a Go wizard but based on what people are telling me there are only read and write timeout settings but not hanging up idle connections.

Now my server will fill up with connections and die unless I set a set read and write timeouts, but the problem with this is my backend takes a long time sometimes and it's causing good requests to be cut off when they shouldn't.

What is the proper way to handle idle connections with Go http?

Edit 1: To be more clear, I'm using httputil.NewSingleHostReverseProxy to construct a proxy, which exposes transport options but only for the upstream. The problems I am having are downstream, they need to be set on the http.Server object that uses the ReverseProxy as a handler. http.Server does not expose transport.

Edit 2: I would prefer an idle timeout to a read timeout, since the later would apply to an active uploader.

Thanks


Solution

  • As of Go 1.8, use Server.IdleTimeout to set a timeout for idle connections.


    Answer for Go 1.7 and earlier:

    The proper way to hangup idle connections in the Go http server is to set the read timeout.

    It is not necessary to set the write timeout to hang up on idle clients. Don't set this value or adjust it up if it's cutting off responses.

    If you have long uploads, then use a connection state callback to implement separate idle and read timeouts:

    server.ConnState = func(c net.Conn, cs http.ConnState) {
        switch cs {
        case http.StateIdle, http.StateNew:
            c.SetReadDeadline(time.Now() + idleTimeout)
        case http.StateActive:
            c.SetReadDeadline(time.Now() + activeTimeout)
        }
    }