2012-06-10 27 views
19

Tôi đã đặt một máy chủ http được viết bằng Go và nó nhận được một ít hơn một nghìn khách truy cập mỗi ngày. Tôi có một vấn đề tích lũy Goroutine bây giờ. Trong một ngày, tôi dường như nhận được hơn một nghìn Goroutine mới từ máy chủ http.Golang: http server để mở các goroutines

Tôi không chắc chắn làm thế nào tôi có thể gây rối xử lý.

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

Dưới đây là một trong những goroutines từ stack

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 

Nó có vẻ như kết nối được bị mắc kẹt trong tình trạng đọc. Giống như máy chủ http không định thời gian chúng ra. Máy chủ mặc định không có thời gian chờ đã đọc chưa?

phiên bản go1

Trả lời

54

Lý do tất cả các goroutines đang đọc vẫn còn hoạt động. Khi trình duyệt gửi tiêu đề tiếp tục tồn tại, máy chủ sẽ giữ kết nối mở để chấp nhận nhiều yêu cầu hơn. Đây là một điều tốt khi khách hàng yêu cầu nhiều tệp nhỏ và kết nối TCP là chi phí đáng kể. Thời gian chờ đọc sẽ đảm bảo rằng không có kết nối nào được giữ lâu hơn một thời gian nhất định giữa các yêu cầu. Điều này sẽ đóng các kết nối còn sống nhưng cũng ngăn người khác tải lên lâu hơn thời gian chờ. Thật không may, không có tùy chọn thời gian chờ cụ thể tiếp tục.

Theo mặc định, không có thời gian chờ. Bạn có thể thiết lập một thời gian chờ trong struct server 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

Cảm ơn! Tôi sẽ thử cho bản cập nhật của chúng tôi trong tuần này. :-) – Daniel

+1

Đúng, đã sửa nó. Cảm ơn! – Daniel

+0

Bạn có thể đánh dấu nó là đã trả lời không? Cảm ơn –

0

Hãy cẩn thận về việc sử dụng ReadTimeout và WriteTimeout trên các kết nối HTTP. Tôi không nghĩ rằng họ làm những gì bạn mong đợi họ. Đặc biệt, họ có xu hướng để lại các kết nối trong trạng thái không sử dụng được mà không thực sự đóng chúng lại. Xem https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ để biết chi tiết, đặc biệt, tôi thấy các trường hợp trong đó ReadTimeout khiến các kết nối không sử dụng được và khiến các phản hồi bị giảm trên sàn khi thời gian xử lý HTTP vượt quá thời gian chờ. Nếu bạn đặt thời gian chờ thành một giá trị lớn vượt quá thời gian phản hồi của bất kỳ trình xử lý nào, bạn có thể OK.

0

Câu trả lời của Stephen chỉ làm việc cho tôi kết hợp với những điều sau đây: máy chủ có thể nói với khách hàng rằng nó không muốn hoặc hỗ trợ để duy trì kết nối. Để làm như vậy, đặt cờ theo trước khi phục vụ:

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

này sẽ thiết lập các tiêu đề phản ứng Connection: closenhất khách hàng sẽ chấm dứt kết nối từ phía họ.

Các vấn đề liên quan