在Go中创建空闲超时?

时间:2015-03-29 20:23:41

标签: http go connection

我将CloudFlare用于我的一个高容量网站,它位于我的堆栈前面。

事情是CloudFlare除了创建新的连接外,还会打开空闲连接,这不是我可以改变的设置。

当我让Varnish或Nginx坐在前面侦听端口80时,他们已经开箱即用配置来挂断空闲连接。

这很好,直到我必须添加一个用Go编写的代理到我的堆栈前面。它使用net/http标准库。

我不是Go向导,但根据人们告诉我的内容,只有读取和写入超时设置,但不会挂起空闲连接。

现在我的服务器将填满连接和死亡,除非我设置一组读取和写入超时,但问题是我的后端有时需要很长时间,并且它导致好的请求被切断,当他们不应该。

使用Go http处理空闲连接的正确方法是什么?

编辑1:为了更清楚,我正在使用httputil.NewSingleHostReverseProxy来构建代理,该代理公开传输选项但仅针对上游。我遇到的问题是下游问题,需要在使用ReverseProxy作为处理程序的http.Server对象上进行设置。 http.Server不会公开传输。

编辑2:我希望空闲超时到读取超时,因为后者将应用于活动上传器。

由于

2 个答案:

答案 0 :(得分:5)

在Go http服务器中挂起空闲连接的正确方法是设置read timeout

没有必要将写入超时设置为挂起空闲客户端。如果它正在切断响应,请不要设置此值或进行调整。

如果上传时间较长,请使用a connection state callback实现单独的空闲和读取超时:

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)
    }
}

答案 1 :(得分:0)

请参阅net/http.Transport文档。 Transport类型有一些选项可用于处理保持活动状态下的空闲HTTP连接。通过阅读您的问题,与您的问题最相关的选项是MaxIdleConnsPerHost字段:

  

MaxIdleConnsPerHost,如果非零,则控制最大空闲(保持活动)以保持每个主机。如果为零,则使用DefaultMaxIdleConnsPerHost。

阅读代码,默认值为每个主机2个。

传输类型还有一种方法来消除所有空闲连接:CloseIdleConnections。

  

CloseIdleConnections将关闭先前从先前请求连接的所有连接,但现在处于空闲状态并保持在" keep-alive"州。它不会中断当前正在使用的任何连接。

您可以在任何http客户端上指定传输:

tr := &http.Transport{
    TLSClientConfig:    &tls.Config{RootCAs: pool},
    DisableCompression: true,
    MaxIdleConnsPerHost: 1,
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://example.com")

另一件值得注意的事情是:文档建议您保留一个在所有请求中重复使用的http客户端对象(例如全局变量)。

  

客户端和传输对于多个goroutine并发使用是安全的,并且效率应该只创建一次并重新使用。

如果您在代理实现中创建了许多http客户端对象,它可能解释了空闲连接的无限增长(尽管猜测您可能如何实现这一点)。

编辑:再多一点,net / httputil包有一些反向代理的便利类型。请参阅ReverseProxy type。该结构还允许您提供自己的Transport对象,允许您通过此帮助程序类型控制代理的空闲客户端行为。