2014-11-14 13 views
7

से कनेक्ट होने पर यूनिक्स सॉकेट टीसीपी से धीमी है, मैं उच्च प्रदर्शन वेब सर्वर विकसित कर रहा हूं जो ~ 2k एक साथ कनेक्शन और 40k क्यूपीएस को संभाल लेना चाहिए, < 7ms को प्राप्त करना चाहिए।
रेडिस

यह क्या करता है रेडिस सर्वर (उसी होस्ट पर चल रहा है) और क्लाइंट को प्रतिक्रिया वापस करने से पूछताछ करता है। परीक्षण के दौरान, मैंने देखा कि टीसीपी STREAM_SOCKET का उपयोग कर कार्यान्वयन यूनिक्स सॉकेट से कनेक्ट करने से बेहतर तरीके से कार्य करता है। ~ 1500 कनेक्शन के साथ टीसीपी लगभग 8ms रहता है जबकि यूनिक्स सॉकेट ~ 50 तक आते हैं।

सर्वर सी में लिखा गया है, यह स्थिर पॉज़िक्स थ्रेड पूल पर आधारित है, मैं रेडिस से अवरुद्ध कनेक्शन का उपयोग करता हूं। मेरा ओएस सेंटोस 6 है, परीक्षण जेएमटर, wrk और ab का उपयोग करके किया गया था। रेडिस के साथ कनेक्शन के लिए मैं किराए पर लेता हूं lib जो रेडिस से जुड़ने के इन दो तरीकों को प्रदान करता है।
जहां तक ​​मुझे पता है कि यूनिक्स सॉकेट कम से कम टीसीपी जितना तेज़ होना चाहिए।

क्या किसी को कोई विचार है कि इस तरह के व्यवहार का कारण क्या हो सकता है? । मैं फँस गया हूँ। धन्यवाद।

+1

आप इस धीमी गति अपने आवेदन का उपयोग कर 'redis-benchmark' के बाहर दोहराने कर सकते हैं? –

+1

[इस लिंक] के अनुसार (http://redis.io/topics/benchmarks) टीसीपी/आईपी लूपबैक की तुलना में यूनिक्स डोमेन सॉकेट का प्रदर्शन लाभ घटता है जब पाइपलाइनिंग का भारी उपयोग होता है (यानी लंबी पाइपलाइन)। – helloV

+0

क्या आप SO_NODELAY सेट करते हैं? मैंने कुछ स्थितियों में यह मदद बहुत देखी है। – geert3

उत्तर

15

यूनिक्स डोमेन सॉकेट आमतौर पर लूपबैक इंटरफ़ेस पर टीसीपी सॉकेट से तेज़ होते हैं। आम तौर पर यूनिक्स डोमेन सॉकेट में औसत 2 माइक्रोसॉन्ड विलंबता होती है जबकि टीसीपी सॉकेट 6 माइक्रोसेकंड होता है।

यदि मैं डिफॉल्ट (कोई पाइपलाइन) के साथ रेडिस-बेंचमार्क चलाता हूं तो मुझे प्रति सेकेंड 160k अनुरोध दिखाई देता है, मूल रूप से क्योंकि एकल-थ्रेडेड रेडिस सर्वर टीसीपी सॉकेट द्वारा सीमित होता है, 160 माइक्रोसॉफ्ट के औसत प्रतिक्रिया समय पर 160k अनुरोध चलते हैं।

यूनिक्स डोमेन सॉकेट का उपयोग करते समय रेडोस प्रति सेकंड 320k एसईटी/जीईटी अनुरोध प्राप्त करता है।

लेकिन एक सीमा है, जो वास्तव में, टॉरसवेयर पर हमारे उत्पाद Speedus के साथ पहुंच गई है, 200 नैनोसेकंड की औसत विलंबता के साथ एक उच्च-प्रदर्शन टीसीपी सॉकेट कार्यान्वयन (अनुरोध के लिए [email protected] पर हमें पिंग करें चरम प्रदर्शन संस्करण)। लगभग शून्य विलंबता के साथ हम प्रति सेकंड लगभग 500k अनुरोध प्राप्त करने वाले रेडिस-बेंचमार्क देखते हैं। तो हम कह सकते हैं कि रेडिस-सर्वर विलंबता औसत पर प्रति अनुरोध लगभग 2 माइक्रोसॉन्ड है।

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

इस प्रकार, पिछले परिदृश्य पर, 32 अनुरोधों की पाइपलाइन के साथ (सॉकेट के माध्यम से वास्तविक अनुरोध भेजने से पहले 32 अनुरोधों को बफर करना) आप लूपबैक इंटरफ़ेस पर प्रति सेकंड 1 मिलियन अनुरोधों को संसाधित कर सकते हैं। और इस परिदृश्य में जहां यूडीएस लाभ उच्च नहीं हैं, विशेष रूप से क्योंकि इस तरह की पाइपलाइनिंग प्रसंस्करण प्रदर्शन बाधा है। वास्तव में, 32 की पाइपलाइन के साथ 1 एम अनुरोध प्रति सेकंड लगभग 31k "वास्तविक" अनुरोध हैं, और हमने देखा है कि रेडिस-सर्वर प्रति सेकंड 160k अनुरोधों को संभालने में सक्षम है।

यूनिक्स डोमेन सॉकेट क्रमश: 1.1 एम और 1.7 एम सेट/प्रति सेकंड अनुरोध प्राप्त करते हैं। टीसीपी लूपबैक प्रति सेकंड 1 एम और 1.5 एसईटी/जीईटी अनुरोध संभालती है।

बाधा डालने के साथ परिवहन प्रोटोकॉल से पाइपलिंग हैंडलिंग तक चलती है।

यह redis-benchmark साइट में उल्लिखित जानकारी के अनुरूप है।

हालांकि, पाइपलाइनिंग नाटकीय रूप से प्रतिक्रिया समय बढ़ जाती है।इस प्रकार, बिना पाइपलाइनिंग के 100% ऑपरेशन आम तौर पर 1 मिलीसेकंड से कम में चलते हैं। 32 अनुरोधों को पाइपलाइन करते समय अधिकतम प्रतिक्रिया समय उच्च प्रदर्शन सर्वर में 4 मिलीसेकंड होता है, और मिलीसेकंड के दसियों यदि रेडिस-सर्वर एक अलग मशीन या वर्चुअल मशीन में चलता है।

तो आपको प्रतिक्रिया समय और अधिकतम थ्रूपुट से व्यापार करना होगा।

+3

यह अजीब बात है कि किसी ने इस लंबे और अच्छे जवाब पर कोई टिप्पणी नहीं की है। अपने अनुभव साझा करने के लिए धन्यवाद! – scaryguy

1

हालांकि यह एक पुराना सवाल है, मैं एक अतिरिक्त बनाना चाहता हूं। अन्य उत्तरों 500k या यहां तक ​​कि 1.7 एम प्रतिक्रियाओं के बारे में बात करते हैं। यह Redis के साथ प्राप्त किया जा सकता है, लेकिन प्रश्न यह था:

क्लाइंट - # नेटवर्क # -> वेबसर्वर - # कुछ # -> Redis

Redis के लिए एक एचटीएमएल प्रॉक्सी की तरह में वेबसर्वर कार्यों मै मानता हूँ।

इसका मतलब है कि आपके अनुरोधों की संख्या भी सीमित है कि वेबसर्वर कितने अनुरोध प्राप्त कर सकता है। एक सीमा अक्सर भूल जाती है: यदि आपके पास 100 एमबीटी कनेक्शन है, तो आपके पास अपने निपटारे में एक सेकंड में 100,000.000 बिट्स हैं, लेकिन 1518 बिट्स के पैकेज में डिफ़ॉल्ट (पैकेज के बाद आवश्यक स्थान सहित)। इसका मतलब है: 65 के नेटवर्क पैकेज। मान लें कि आपके सभी प्रतिक्रियाएं कम हैं कि ऐसे पैकेज का डेटा हिस्सा और गैर को सीआरसी त्रुटियों या खोए गए पैकेजों के कारण पुनः भेजना होगा।

इसके अलावा, यदि लगातार कनेक्शन का उपयोग नहीं किया जाता है, तो आपको प्रत्येक कनेक्शन के लिए एक टीसीपी/आईपी हैंडशेक करने की आवश्यकता है यह प्रति अनुरोध 3 पैकेज जोड़ता है (2 प्राप्त करता है, एक भेजता है)। तो उस अप्रत्याशित स्थिति में, आप अपने वेबसर्वर को 21k प्राप्य अनुरोध के साथ रहते हैं। (या एक 'सही' गीगाबिट कनेक्शन के लिए 210k) - यदि आपकी प्रतिक्रिया 175 बाइट्स के एक पैकेट में फिट बैठती है।

तो:

  • लगातार कनेक्शन केवल स्मृति का एक सा की आवश्यकता होती है, तो यह सक्षम करें। यह आपके प्रदर्शन को चौगुनी कर सकता है। (सबसे अच्छा मामला)
  • यदि आवश्यक हो तो gzip/deflate का उपयोग कर अपने प्रतिक्रिया आकार को कम करें ताकि वे जितना संभव हो उतने पैकेट में फिट हो जाएं। (खो गया प्रत्येक पैकेट एक संभावित प्रतिक्रिया खो गया है)
  • डीबग डेटा या लंबे एक्सएमएल टैग जैसे अनियंत्रित 'कचरा' को अलग करके अपने प्रतिक्रिया आकार को कम करें।
  • HTTPS कनेक्शन एक विशाल जोड़ देगा (comparisation में यहाँ) भूमि के ऊपर
  • , नेटवर्क कार्ड जोड़ें और उन्हें
  • ट्रंक प्रतिक्रियाएं हमेशा से रहे हैं अगर कम है तो 175 बाइट्स इस सेवा के लिए एक dedicted नेटवर्क कार्ड का उपयोग करें और नेटवर्क फ्रेम आकार को कम पैकेज को बढ़ाने के लिए प्रत्येक सेकेंड भेजें।
  • न दें सर्वर अन्य बातों (सामान्य वेब पृष्ठों की सेवा की तरह)
  • ...