2012-06-10 33 views
19

我已經搭起了一個用Go編寫的http服務器,它每天的訪問量有一千多人。我現在有一個積累的Goroutine問題。在一天的過程中,我似乎從http服務器獲得了一千多個新的Goroutine。Golang:http服務器離開開放式goroutines

我不知道我怎麼會搞砸處理程序。

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

下面是從堆棧

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版本go1

回答

54

所有這些goroutines正在閱讀的原因是保持活力。當瀏覽器發送保持活動頭時,服務器會保持連接處於打開狀態以接受更多請求。當客戶端請求很多小文件時,這是一件好事,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() 
+0

謝謝!我會在本週嘗試我們的更新。 :-) – Daniel

+1

是的,那是固定的。謝謝! – Daniel

+0

你能把它標記爲已回答嗎?謝謝 –

0

小心使用ReadTimeout和WriteTimeout的HTTP連接。我認爲他們沒有達到你期望的水平。特別是,他們傾向於在沒有實際關閉它們的情況下使連接處於不可用狀態。有關詳細信息,請參閱https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ,特別是,我看到ReadTimeout使連接無法使用並導致響應在HTTP處理程序時間超過超時時間時被丟棄的情況。如果您將超時設置爲超過任何處理程序的響應時間的較大值,則可能是正確的。

0

Stephen的答案只適用於以下情況:服務器可以告訴它的客戶,它不希望或不支持保持連接打開。要做到這一點,在食用前設置根據標誌:

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

這將設置響應頭Connection: close客戶將終止從他們身邊的連接。