2009-08-01 6 views
32

जब भी मैं एक वेब सर्वर बेंचमार्क करने के लिए 'ab' का उपयोग करता हूं, तो यह बहुत से अनुरोध भेजे जाने के बाद थोड़ी देर के लिए स्थिर हो जाएगा, केवल 20 सेकंड या उसके बाद जारी रखने के लिए।'ab' प्रोग्राम बहुत सारे अनुरोधों के बाद जमा हो जाता है, क्यों?

पर विचार करें निम्नलिखित HTTP सर्वर सिम्युलेटर, रूबी में लिखा:

require 'socket' 

RESPONSE = "HTTP/1.1 200 OK\r\n" + 
      "Connection: close\r\n" + 
      "\r\n" + 
      "\r\n" 

buffer = "" 
server = TCPServer.new("127.0.0.1", 3000) # Create TCP server at port 3000. 
server.listen(1024)      # Set backlog to 1024. 
while true 
    client = server.accept    # Accept new client. 
    client.write(RESPONSE)    # Write a stock "HTTP" response. 
    client.close_write     # Shutdown write part of the socket. 
    client.read(nil, buffer)   # Read all data from the socket. 
    client.close      # Close it. 
end 

मैं तो अब चलाने के इस प्रकार है: के रूप में यह चाहिए था

ab -n 45000 -c 10 http://127.0.0.1:3000/ 

पहले कुछ सेकंड के दौरान, अब अपने काम करता है और 100% सीपीयू का उपयोग करता है:

Benchmarking 127.0.0.1 (be patient) 
Completed 4500 requests 
Completed 9000 requests 
Completed 13500 requests 

लगभग 13500 अनुरोधों के बाद, सिस्टम सीपीयू उपयोग टी ड्रॉप ओ 0% अब कुछ पर जमे हुए प्रतीत होता है। समस्या सर्वर में नहीं है क्योंकि इस समय, सर्वर स्वीकार() को कॉल कर रहा है। लगभग 20 सेकंड के बाद जारी रहता है जैसे कुछ भी नहीं हुआ, और फिर से 100% CPU का उपयोग करेगा, केवल कई सेकंड के बाद फिर से फ्रीज करने के लिए।

मुझे संदेह है कि कर्नेल में कुछ थ्रॉटलिंग कनेक्शन है, लेकिन क्या और क्यों? मैं ओएस एक्स तेंदुए का उपयोग कर रहा हूँ। मैंने लिनक्स पर भी इसी तरह के व्यवहार को देखा है, हालांकि फ्रीज अनुरोधों की एक बड़ी संख्या में होता है और ऐसा अक्सर नहीं होता है।

यह समस्या मुझे बड़े HTTP मानक चलाने से रोकती है।

उत्तर

47

ऐसा लगता है कि आप ephemeral ports से बाहर चल रहे हैं। जांचने के लिए, netstat कमांड का उपयोग करें और TIME_WAIT स्थिति में कई हजार बंदरगाहों को देखें।

मैक ओएस एक्स पर कुल 16384 बंदरगाहों के लिए डिफ़ॉल्ट क्षणिक पोर्ट रेंज 49152 से 65535 है।

 
$ sysctl net.inet.ip.portrange.first net.inet.ip.portrange.last 
net.inet.ip.portrange.first: 49152 
net.inet.ip.portrange.last: 65535 

एक बार जब आप अल्पकालिक बंदरगाहों से बाहर चलाने, आप सामान्य रूप से जब तक TIME_WAIT राज्य समाप्त हो रहा है (2 * अधिकतम खंड जीवनकाल) प्रतीक्षा करने के लिए जब तक आप एक विशेष पोर्ट संख्या का पुन: उपयोग कर सकते हैं की आवश्यकता होगी: आप sysctl आदेश के साथ इस जाँच कर सकते हैं । आप 32768 पर शुरू करने के लिए रेंज को बदलकर बंदरगाहों की संख्या को दोगुना कर सकते हैं, जो कि लिनक्स और सोलारिस पर डिफ़ॉल्ट है। (अधिकतम पोर्ट संख्या 65535 ताकि आप उच्च अंत में वृद्धि नहीं कर सकते हैं।)

 
$ sudo sysctl -w net.inet.ip.portrange.first=32768 
net.inet.ip.portrange.first: 49152 -> 32768 

ध्यान दें कि official range designated by IANA 65535 करने के लिए को 49152 पोर्ट है, और कुछ फायरवॉल मान सकते हैं कि गतिशील रूप से आवंटित बंदरगाहों उस सीमा के भीतर गिर जाते हैं। अपने स्थानीय नेटवर्क के बाहर एक बड़ी सीमा का उपयोग करने के लिए आपको अपने फ़ायरवॉल को फिर से कॉन्फ़िगर करना पड़ सकता है।

यह भी अधिकतम खंड जीवनकाल (sysctl net.inet.tcp.msl मैक ओएस एक्स पर) है, जो TIME_WAIT राज्य की अवधि को नियंत्रित करता है कम करने के लिए संभव है, लेकिन यह के रूप में यह पुराने कनेक्शन नए होते हैं कि के साथ मिश्रित करने के लिए कारण हो सकता है खतरनाक है एक ही पोर्ट नंबर का उपयोग कर। SO_REUSEADDR विकल्प के साथ विशिष्ट पोर्ट्स को बाध्यकारी या SO_LINGER विकल्प के साथ बंद करने वाली कुछ चालें भी हैं, लेकिन वे पुराने और नए कनेक्शन को मिश्रित करने का कारण भी बना सकते हैं, इसलिए आमतौर पर खराब विचार माना जाता है। बंदरगाहों की संख्या में वृद्धि की

+1

हाँ, यही वह है। मैंने http://www.brianp.net/2008/10/03/changing-the-length-of-the-time_wait-state-on-mac-os-x/ पर निर्देशों का पालन करके एमएसएल को बदल दिया और सब कुछ काम करता है अभी व। धन्यवाद! – Hongli

+0

बहुत बहुत धन्यवाद, यह वही समस्या तय कर रहा था जो मैं कर रहा था। –

+0

यहां मैं सोच रहा था कि यह 'गोलांग' समस्या थी .. जब यह '16' से प्रत्येक 16000 अनुरोधों को जम गया – kouton

16

इसके बजाय,

विकास में यह केवल काम करता है मैक ओएस एक्स पर TIME_WAIT की लंबाई को बदल, लेकिन मैं अब के रूप में कई अनुरोधों के लिए ab पूछने के रूप में मैं समय बाहर के बिना चाहते हैं कर सकते हैं।

सेट डिफ़ॉल्ट टाइमआउट तो जैसे 1000ms करने के लिए:

$ sudo sysctl -w net.inet.tcp.msl=1000 
net.inet.tcp.msl: 15000 -> 1000 

brianp.net पेज अन्य जवाब में बताया गया अब उपलब्ध नहीं है। आप इसे internet archive से पुनर्प्राप्त कर सकते हैं।

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