2012-06-10 18 views
19

Go'da yazılmış bir http sunucusunu hazırladım ve günde binlerce ziyaretçiye ulaşıyorum. Şimdi biriken bir Goroutine problemim var. Bir gün boyunca, http sunucusundan binlerce yeni Goroutines almayı düşünüyorum.Golang: http sunucusu açık goroutines'i bırakıyor

İşleyiciyi nasıl dağıtacağımı bilmiyorum.

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

Aşağıda bağlantıları okuma halde sıkışmış gibi görünüyor yığını

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 

gelen goroutines biridir. Http sunucusu onları zamanlama gibi değil. Varsayılan sunucunun okuma zaman aşımı yok mu? Tüm bu goroutines okuduğunuz

go versiyonu GO1

cevap

54

nedeni canlı tutma olduğunu. Bir tarayıcı canlı tutma başlığı gönderdiğinde, sunucu daha fazla istek kabul etmek için bağlantıyı açık tutar. İstemci çok sayıda küçük dosya istediğinde ve TCP bağlantısı önemli bir yük olduğunda bu iyi bir şeydir. Okunmuş zaman aşımı, isteklerin herhangi bir zamanda belirli bir süreden daha fazla canlı kalmamasını sağlar. Bu, canlı bağlantıları yakın tutmaya devam edecek, ancak aynı zamanda bir kullanıcının zaman aşımından daha uzun süre yüklemesini de engelleyecektir. Maalesef, henüz canlı bir özel zaman aşımı seçeneği yoktur.

Varsayılan olarak, zaman aşımı yok. Sen 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

Teşekkürler! Bu hafta güncellememiz için bir deneme yapacağım. :-) – Daniel

+1

Evet, bu düzeltildi. Teşekkürler! – Daniel

+0

Yanıt olarak işaretleyebilir misiniz? Teşekkürler –

0

HTTP bağlantılarında ReadTimeout ve WriteTimeout kullanma konusunda dikkatli olun Sunucu yapı içinde bir zaman aşımı ayarlayabilirsiniz. Onlara beklediğiniz şeyi yaptıklarını sanmıyorum. Özellikle, bağlantıları fiilen kapatmadan kullanılamayan bir durumda bırakma eğilimi vardır. Ayrıntılar için bkz. https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ, ReadTimeout'un bağlantıları kullanılamaz hale getirdiği ve HTTP işleyicisi zaman aşımını aştığında yanıtların yere bırakılmasına neden olan durumları görüyorum. Zaman aşımını herhangi bir işleyicinin yanıt süresini aşan büyük bir değere ayarlarsanız Tamam olabilirsiniz.

0

Stephen'ın yanıtı sadece aşağıdakilerle birlikte çalıştı: Sunucu, istemcilerini bağlantılarını açık tutmak istemediğini veya desteklemediğini söyleyebilir. Bunu yapmak için, servis etmeden önce uygun bayrağını ayarlayın:

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

Bu onların tarafında bağlantıyı sonlandırır yanıt başlığını Connection: close ve en istemcileri ayarlayacaktır.