我将CloudFlare用于我的一个高容量网站,它位于我的堆栈前面。
事情是CloudFlare除了创建新的连接外,还会打开空闲连接,这不是我可以改变的设置。
当我让Varnish或Nginx坐在前面侦听端口80时,他们已经开箱即用配置来挂断空闲连接。
这很好,直到我必须添加一个用Go编写的代理到我的堆栈前面。它使用net/http
标准库。
我不是Go向导,但根据人们告诉我的内容,只有读取和写入超时设置,但不会挂起空闲连接。
现在我的服务器将填满连接和死亡,除非我设置一组读取和写入超时,但问题是我的后端有时需要很长时间,并且它导致好的请求被切断,当他们不应该。
使用Go http处理空闲连接的正确方法是什么?
编辑1:为了更清楚,我正在使用httputil.NewSingleHostReverseProxy
来构建代理,该代理公开传输选项但仅针对上游。我遇到的问题是下游问题,需要在使用ReverseProxy作为处理程序的http.Server
对象上进行设置。 http.Server
不会公开传输。
编辑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对象,允许您通过此帮助程序类型控制代理的空闲客户端行为。