2012-05-09 9 views
9

मेरे पास Nginx/यात्री पर रेल 3 एप था जो मैं अभी Nginx/Thin (1.3.1) में स्थानांतरित हो गया था। हालांकि, मेरे ऐप अब पैसेंजर पर स्पष्ट रूप से धीमा है। बहुत सारे अनुरोध भी समय समाप्त हो गए हैं।पतला सर्वर अंडरफॉर्मिंग/ईवेंट किए गए वेब सर्वर कैसे काम करते हैं?

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

हालांकि, मेरा सीपीयू उपयोग बहुत कम है। मेरी याददाश्त का उपयोग बहुत कम है, और वहां बहुत कुछ नहीं हो रहा है। मेरा ऐप सिर्फ कुछ MySQL प्रश्न बनाता है।

यहां बाधा क्या है? सीपीयू 100% पर होने तक मेरा पतला सर्वर संभाल अनुरोध नहीं करना चाहिए? क्या किसी ईवेंट किए गए सर्वर के साथ बेहतर प्रदर्शन करने के लिए मुझे अपने ऐप में कुछ भी अलग करना है?

उत्तर

13

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

यह एसिंक्रोनस (घटनाक्रम) प्रोग्रामिंग को कठिन बनाता है - सामानों को अवरुद्ध करना आसान है, आमतौर पर सिंक्रोनस डिस्क I/O या DNS संकल्प के रूप में। गैर-अवरुद्ध (घटनाबद्ध) ढांचे जैसे कि नोडजेस सावधान हैं कि वे (लगभग) आपको कभी भी फ्रेमवर्क फ़ंक्शन कॉल प्रदान नहीं करते हैं जो अवरुद्ध हो रहा है, बल्कि कॉलबैक (डीबी क्वेरी सहित) का उपयोग करके सबकुछ संभाला जाता है।

यह कल्पना करने के लिए आसान है, तो आपको एक बार पिरोया गैर अवरुद्ध सर्वर के दिल में देखो हो सकता है:

while(wait_on_sockets(/* list<socket> */ &$sockets, /* event */ &$what, $timeout)) { 
    foreach($socketsThatHaveActivity as $fd in $sockets) { 
     if($what == READ) { // There is data availabe to read from this socket 
      $data = readFromSocket($fd); 
      processDataQuicklyWithoutBlocking($data); 
     } 
     elseif ($what == WRITE && $data = dataToWrite($fd)) { // This socket is ready to be written to (if we have any data) 
      writeToSocket($fd, $data);  
     } 
    } 
} 

क्या आपने ऊपर देखा, घटना पाश कहा जाता है। wait_on_sockets आमतौर पर ओएस द्वारा सिस्टम कॉल के रूप में प्रदान किया जाता है, जैसे चयन, चुनाव, एपोल, या क्यूक्यू। यदि प्रक्रिया DataQuicklyWithoutBlocking बहुत अधिक समय लेता है, तो ओएस (नए अनुरोध, आने वाले डेटा इत्यादि) द्वारा बनाए गए आपके एप्लिकेशन का नेटवर्क बफर अंततः भर जाएगा, और इसे नए कनेक्शन और टाइमआउट को मौजूदा लोगों को अस्वीकार कर देगा, क्योंकि $ socketsThatHaveActivity को पर्याप्त तेज़ी से संभाला नहीं जा रहा है । यह थ्रेडेड सर्वर से अलग है (उदाहरण के लिए एक विशिष्ट अपाचे इंस्टॉल) जिसमें प्रत्येक कनेक्शन को अलग थ्रेड/प्रक्रिया का उपयोग करके परोसा जाता है, इसलिए जैसे ही आने वाला डेटा ऐप में पढ़ेगा, और आउटगोइंग डेटा बिना देरी के भेजा जाएगा ।

जब आप बनाते हैं तो नोडज की तरह गैर-अवरुद्ध ढांचे क्या करते हैं (उदाहरण के लिए) डीबी क्वेरी डीबी सर्वर के सॉकेट कनेक्शन को मॉनिटर ($ सॉकेट) की सूची में जोड़ना है, इसलिए यदि आपकी क्वेरी लेती है थोड़ी देर में, आपका (केवल) धागा उस सॉकेट पर अवरुद्ध नहीं है। बल्कि वे एक कॉलबैक प्रदान करते हैं:

$db.query("...sql...", function($result) { ..handle result ..}); 

ऊपर दिखने वाला, db.query जो भी db सर्वर पर बिल्कुल नहीं अवरुद्ध साथ तुरंत वापस लौट सकते हैं।यह भी मतलब है आप बार-बार, जब तक कि प्रोग्रामिंग भाषा में ही async कार्य (जैसे नए सी #) का समर्थन करता है इस तरह कोड लिखने के लिए है:

$db.query("...sql...", function($result) { $httpResponse.write($result); $connection.close(); }); 

कभी न कभी-ब्लॉक नियम कुछ हद तक आराम अगर आप कई प्रक्रियाओं है हो सकता है जो प्रत्येक इवेंट लूप (आमतौर पर नोड क्लस्टर चलाने का तरीका) चला रहे हैं, या इवेंट लूप (जावा की जेटी, नेटटी इत्यादि) को बनाए रखने के लिए थ्रेड पूल का उपयोग करते हैं, आप सी/सी ++ में अपना खुद का लिख ​​सकते हैं)। जबकि एक थ्रेड किसी चीज़ पर अवरुद्ध है, अन्य थ्रेड अभी भी ईवेंट लूप कर सकते हैं। लेकिन भारी भार के तहत, यहां तक ​​कि ये प्रदर्शन करने में विफल रहेगा। तो कभी भी एक घटना सर्वर में ब्लॉक कभी नहीं।

तो जैसा कि आप देख सकते हैं, घटनाक्रम सर्वर आम तौर पर एक अलग समस्या को हल करने का प्रयास करते हैं - उनके पास बहुत से खुले कनेक्शन हो सकते हैं। जहां वे एक्सेल करते हैं, वे प्रकाश गणनाओं के साथ बाइट्स को धक्का दे रहे हैं (उदाहरण के लिए धूमकेतु सर्वर, मेमकैच, वार्निश, कैंक्स जैसे नग्ग्क्स, स्क्विड इत्यादि)। यह कुछ भी मूल्यवान नहीं है कि भले ही वे बेहतर पैमाने पर हों, प्रतिक्रिया समय आम तौर पर बढ़ते हैं (कनेक्शन के लिए पूरे धागे को आरक्षित करने से कुछ भी बेहतर नहीं होता है)। बेशक, यह समवर्ती कनेक्शन के # के रूप में समान संख्या में थ्रेड चलाने के लिए आर्थिक रूप से/कम्प्यूटेशनल रूप से व्यवहार्य नहीं हो सकता है।

अब आपके मुद्दे पर वापस - मैं आपको सलाह देता हूं कि आप अभी भी निजिनक्स को चारों ओर रखें, क्योंकि यह कनेक्शन प्रबंधन (जो घटना-आधारित है) पर उत्कृष्ट है - आमतौर पर HTTP रख-रखाव, एसएसएल इत्यादि को संभालने का मतलब है। आपको इसे कनेक्ट करना चाहिए FastCGI का उपयोग करके अपने रेल ऐप पर, जहां आपको अभी भी श्रमिकों को चलाने की आवश्यकता है, लेकिन पूरी तरह से होने के लिए अपने ऐप को फिर से लिखना नहीं है। आपको Nginx को स्थैतिक सामग्री भी प्रदान करने देना चाहिए - आपके रेल श्रमिकों को कुछ ऐसी चीज से बंधने में कोई बात नहीं है जो Nginx आमतौर पर बेहतर कर सकता है। यह दृष्टिकोण आमतौर पर अपाचे/पैसेंजर से काफी बेहतर है, खासकर यदि आप एक उच्च ट्रैफिक वेबसाइट चलाते हैं।

यदि आप अपना पूरा ऐप ईवेंट करने के लिए लिख सकते हैं, तो महान, लेकिन मुझे नहीं पता कि रुबी में कितना आसान या मुश्किल है।

+0

वाह .. विस्तृत प्रतिक्रिया Tejas के लिए धन्यवाद। तो बेंचमार्क जो मैंने नेट को पढ़ा .. क्या वे पूरी तरह से अलग एप्लिकेशन शैली के लिए हैं? पतली अपनी साइट पतली के लिए उदाहरण ऐप के रूप में एक रेल ऐप देता है। http://code.macournoyer.com/thin/। मैं इस धारणा का था कि मैं बस यात्री को पतले से बदल सकता था और सबकुछ डरावना-डोर होगा। –

+0

जब तक आप कहीं भी अवरुद्ध नहीं करते हैं, तो आप उन बेंचमार्क को फिर से बनाने में सक्षम होना चाहिए। – tejas

3

हां, पतला I/O होता है, लेकिन केवल HTTP भाग के लिए होता है। जिसका अर्थ है कि अनुरोध को संसाधित करते समय यह आने वाले HTTP डेटा प्राप्त कर सकता है। हालांकि, प्रसंस्करण के दौरान आप जो अवरुद्ध I/O करते हैं वह अभी भी अवरुद्ध है। यदि आपका MySQL प्रतिक्रिया देने में धीमा है, तो पतला अनुरोध कतार भर जाएगी।

"अधिक" ईवेंट किए गए वेबसर्वर के लिए आपको Rainbows देखना चाहिए।

+0

हाय सर्जीओ। इन अवधारणाओं की मेरी पैदल यात्री समझ को क्षमा करें। मैंने पढ़ा है कि रेल के लिए mysql2 मणि ​​IO भी होता है। इसके अलावा, यदि ऐसा है, तो एक कार्यकर्ता आधारित सर्वर हमेशा बेहतर नहीं होगा? मैं केवल पतली के 2 उदाहरणों की तरह चल रहा हूं क्योंकि यात्री के 25 उदाहरणों के विपरीत मैं पहले दौड़ रहा था। –

+0

@CoffeeBite: यह *** *** एसिंक कॉल कर सकता है, हाँ, लेकिन यह स्वचालित नहीं है और आपको इसे करने के लिए कोड लिखना होगा। डिफ़ॉल्ट रूप से, यह तुल्यकालिक है। –

+0

@ कॉफ़ीबाइट: "श्रमिक हमेशा बेहतर नहीं होंगे" - सुनिश्चित नहीं है। मैं खुद एक यूनिग्नक्स के पीछे [यूनिकॉर्न] (http://unicorn.bogomips.org/) का उपयोग करता हूं। Nginx HTTP I/O संभालता है और यूनिकॉर्न्स जल्दी से अनुरोधों को पूरा करता है। –

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