2012-06-10 13 views
19

मैंने गो में एक http सर्वर लिखा है और इसे एक दिन में एक हजार से अधिक आगंतुक मिल रहे हैं। मेरे पास अब गोरौटाइन समस्या जमा हो रही है। एक दिन के दौरान मुझे http सर्वर से एक हजार से अधिक नए गोरौटाइन मिलते हैं।गोलांग: ओपन गोरोटाइन्स को छोड़कर http सर्वर

मुझे यकीन नहीं है कि मैं हैंडलर को कैसे गड़बड़ कर सकता हूं।

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 

ऐसा लगता है कनेक्शन की तरह पढ़ने के लिए राज्य में फंस जा रहा है से goroutines से एक है। Http सर्वर की तरह उन्हें समय नहीं दे रहा है। क्या डिफ़ॉल्ट सर्वर में रीड टाइमआउट नहीं है?

जाने संस्करण go1

उत्तर

54

कारण इन सभी goroutines पढ़ रहे हैं जीवित-रखें है। जब कोई ब्राउज़र एक जीवित हेडर भेजता है, तो सर्वर अधिक अनुरोध स्वीकार करने के लिए कनेक्शन को खुला रखता है। यह एक अच्छी बात है जब ग्राहक कई छोटी फाइलों का अनुरोध कर रहा है और टीसीपी कनेक्शन महत्वपूर्ण ओवरहेड है। एक पठन टाइमआउट यह सुनिश्चित करेगा कि अनुरोधों के बीच एक निश्चित समय से अधिक कनेक्शन जीवित नहीं रखा गया हो। यह जीवित कनेक्शन बनाए रखेगा लेकिन किसी को टाइमआउट से अधिक समय तक अपलोड करने से रोक देगा। दुर्भाग्यवश, अभी तक कोई जीवित विशिष्ट टाइमआउट विकल्प नहीं है।

डिफ़ॉल्ट रूप से, कोई टाइमआउट नहीं है। आप सर्वर struct में एक टाइमआउट सेट कर सकते हैं 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

HTTP कनेक्शन पर ReadTimeout और WriteTimeout उपयोग के बारे में सावधान रहें। मुझे नहीं लगता कि वे वही करते हैं जो आप उन्हें उम्मीद करते हैं। विशेष रूप से, उनके पास वास्तव में उन्हें बंद किए बिना एक अनुपयोगी स्थिति में कनेक्शन छोड़ने की प्रवृत्ति होती है। विवरण के लिए https://groups.google.com/forum/#!topic/golang-nuts/oBIh_R7-pJQ देखें, विशेष रूप से, मैं उन मामलों को देखता हूं जहां रीडटाइमआउट कनेक्शन को अनुपयोगी बनाता है और जब HTTP हैंडलर समय टाइमआउट से अधिक हो जाता है तो फर्श पर प्रतिक्रियाएं गिरा दी जाती हैं। यदि आप किसी भी हैंडलर के प्रतिक्रिया समय से अधिक समय के लिए एक बड़े मूल्य पर सेटआउट सेट करते हैं तो आप ठीक हो सकते हैं।

0

स्टीफन का उत्तर केवल मेरे साथ निम्नलिखित संयोजन में काम करता है: सर्वर अपने ग्राहकों को बता सकता है कि यह कनेक्शन को खोलने के लिए इच्छा या समर्थन नहीं करता है। ऐसा करने के लिए, परोसने से पहले अनुसार ध्वज सेट:

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

यह प्रतिक्रिया हेडर Connection: close और सबसे ग्राहकों सेट उनकी तरफ से कनेक्शन समाप्त कर लेंगे होगा।

संबंधित मुद्दे