Golang:http服务器离开开放的goroutines

时间:2012-06-10 19:46:41

标签: http go

我已经建立了一个用Go编写的http服务器,每天有超过一千个访问者。我现在有一个累积的Goroutine问题。在一天的过程中,我似乎从http服务器上获得了一千多个新的Goroutines。

我不确定如何搞砸处理程序。

http.Handle("/", http.FileServer(http.Dir(config.htdocs_path)))

下面是堆栈中的一个goroutines

goroutine 1582 [chan receive]:
net.(*pollServer).WaitRead(0xf84007f680, 0xf84066dea0, 0xf84007aa80, 0xb, 0x1, ...)
        /home/ec2-user/go/src/pkg/net/fd.go:268 +0x73
net.(*netFD).Read(0xf84066dea0, 0xf840ec1000, 0x100000001000, 0x7f7effffffff, 0xf84007c0f0, ...)
        /home/ec2-user/go/src/pkg/net/fd.go:428 +0x1ec
net.(*TCPConn).Read(0xf84068aff8, 0xf840ec1000, 0x100000001000, 0xf800000002, 0x0, ...)
        /home/ec2-user/go/src/pkg/net/tcpsock_posix.go:87 +0xce
io.(*LimitedReader).Read(0xf840d1bc20, 0xf840ec1000, 0x100000001000, 0xdcb00000000, 0x0, ...)
        /home/ec2-user/go/src/pkg/io/io.go:394 +0xc1
bufio.(*Reader).fill(0xf8405b0900, 0xdcb00000000)
        /home/ec2-user/go/src/pkg/bufio/bufio.go:77 +0xf0
bufio.(*Reader).ReadSlice(0xf8405b0900, 0xf840d1bc0a, 0x0, 0x0, 0x0, ...)
        /home/ec2-user/go/src/pkg/bufio/bufio.go:257 +0x1b6
bufio.(*Reader).ReadLine(0xf8405b0900, 0x0, 0x0, 0x0, 0x0, ...)
        /home/ec2-user/go/src/pkg/bufio/bufio.go:283 +0x5b
net/textproto.(*Reader).readLineSlice(0xf840730660, 0xc0, 0x100000000, 0x7f7e00000001)
        /home/ec2-user/go/src/pkg/net/textproto/reader.go:55 +0x4f
net/textproto.(*Reader).ReadLine(0xf840730660, 0xf84061f300, 0x0, 0x48411c)
        /home/ec2-user/go/src/pkg/net/textproto/reader.go:36 +0x25
net/http.ReadRequest(0xf8405b0900, 0xf84061f300, 0x0, 0x0, 0x100000400ccf60, ...)
        /home/ec2-user/go/src/pkg/net/http/request.go:457 +0xb1
net/http.(*conn).readRequest(0xf8402b2b40, 0xf8400e3fc0, 0x0, 0x0, 0xf8405b0a80, ...)
        /home/ec2-user/go/src/pkg/net/http/server.go:240 +0xa8
net/http.(*conn).serve(0xf8402b2b40, 0x0)
        /home/ec2-user/go/src/pkg/net/http/server.go:594 +0x145
created by net/http.(*Server).Serve
        /home/ec2-user/go/src/pkg/net/http/server.go:1040 +0x430

似乎连接陷入了读取状态。就像http服务器没有计时出来。默认服务器没有读取超时吗?

go go go1

3 个答案:

答案 0 :(得分:57)

所有这些goroutine正在阅读的原因是保持活力。当浏览器发送保持活动标头时,服务器会保持连接打开以接受更多请求。当客户端请求许多小文件并且TCP连接开销很大时,这是一件好事。读取超时将确保没有连接在请求之间保持活动超过一定时间。这将关闭保持活动连接,但也阻止某人上传超过超时。不幸的是,还没有保持活动的特定超时选项。

默认情况下,没有超时。您可以在服务器结构http://golang.org/pkg/net/http/#Server

中设置超时
srv := &http.Server{
    Handler: http.FileServer(http.Dir(config.htdocs_path)),
    ReadTimeout: 30*time.Second,
}
srv.ListenAndServe()

答案 1 :(得分:0)

小心在HTTP连接上使用ReadTimeout和WriteTimeout。我不认为他们按照你的期望去做。特别是,它们倾向于将连接保持在不可用状态而不实际关闭它们。有关详细信息,请参阅https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ,特别是,我看到ReadTimeout使连接无法使用的情况,并且当HTTP处理程序时间超过超时时,会导致响应被丢弃。如果将超时设置为超过任何处理程序响应时间的大值,则可能没问题。

答案 2 :(得分:0)

只有结合以下内容,Stephen的回答才对我有用:服务器可以告诉客户它不希望或支持保持连接打开。为此,请在提供之前设置相应的标志:

server := &http.Server{
  // ... see Stephen's answer
}
server.SetKeepAlivesEnabled(false)
server.ListenAndServe()

这将设置响应标头Connection: close大多数客户端将从他们的一方终止连接。