Node.js को सिंगल थ्रेडेड क्यों कहा जाता है? [बन्द है]


255

PHP (या जावा / ASP.NET / रूबी) आधारित वेबसर्वर में हर ग्राहक का अनुरोध एक नए सूत्र पर त्वरित होता है। लेकिन Node.js में सभी ग्राहक एक ही धागे पर चलते हैं (वे समान चर भी साझा कर सकते हैं!) मैं समझता हूं कि मैं / ओ संचालन घटना-आधारित हैं, इसलिए वे मुख्य धागा लूप को ब्लॉक नहीं करते हैं।

मुझे समझ में नहीं आता है कि नोड के लेखक ने इसे सिंगल-थ्रेडेड क्यों चुना? इससे चीजें कठिन हो जाती हैं। उदाहरण के लिए, मैं CPU गहन फ़ंक्शन नहीं चला सकता क्योंकि यह मुख्य थ्रेड को ब्लॉक करता है (और नए क्लाइंट अनुरोध ब्लॉक किए जाते हैं) इसलिए मुझे एक प्रक्रिया को स्पॉन करने की आवश्यकता है (जिसका अर्थ है कि मुझे एक अलग जावास्क्रिप्ट फ़ाइल बनाने और किसी अन्य नोड प्रक्रिया को निष्पादित करने की आवश्यकता है यह)। हालाँकि, PHP सीपीयू गहन कार्यों में अन्य क्लाइंट को ब्लॉक नहीं करता है क्योंकि जैसा कि मैंने उल्लेख किया है कि प्रत्येक क्लाइंट एक अलग धागे पर है। बहु-थ्रेडेड वेब सर्वर की तुलना में इसके क्या लाभ हैं?

नोट: मैंने इसे प्राप्त करने के लिए क्लस्टरिंग का उपयोग किया है, लेकिन यह बहुत सुंदर नहीं है।


12
मैंने हाल ही में एक अच्छा वीडियो (29 मिनट) देखा जिसमें नोड के पीछे के कुछ सिद्धांत थे। मुझे भी लगता है कि आदमी सीपीयू के गहन कार्यों के बारे में बात करता है और संक्षेप में उन्हें कैसे संभालना है: youtube.com/watch?v=L0pjVcIsU6A
whirlwin

24
आप यह जान सकते हैं, लेकिन स्पष्ट होना Node.js एकल-पिरोया नहीं है। आपका जावास्क्रिप्ट कोड एकल-थ्रेडेड चलता है, लेकिन IO संचालन और अन्य चीजें जो प्लगइन्स थ्रेड पूल से बाहर चला सकती हैं। Node.js आपको मल्टीथ्रेड कोड के साथ सौदा किए बिना मल्टीथ्रेडिंग का अधिक लाभ देता है। इसके अलावा, Node.js योगदानकर्ताओं ने जावास्क्रिप्ट के एकल-थ्रेडेड प्रकृति को नहीं चुना, जावास्क्रिप्ट के लेखकों ने किया। मैं ऐसा नहीं सोच सकता कि जेएस एक बहुपरत संदर्भ में काम कर सकता है, लेकिन यहां तक ​​कि अगर थे, तो वी 8 को उस तरह से नहीं लिखा गया है जो कि Node.js अपने जावास्क्रिप्ट इंजन के रूप में उपयोग करता है।
ब्रैड

5
PHP जावास्क्रिप्ट की तुलना में अधिक एकल-थ्रेडेड है। आप शायद FastCGI या mod_php जैसे सर्वर मॉड्यूल के बारे में सोच रहे हैं। तो आप वास्तव में Apache, Nginx या IIS के साथ Node.js की तुलना कर रहे हैं — PHP, Java या Ruby के साथ नहीं।
अल्वारो गोंजालेज

34
नोड एकल-थ्रेडेड नहीं है। यह एक लोकप्रिय गलत धारणा है। यहां तक ​​कि सरल मेरे सिस्टम पर पांच धागेnode -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $! प्रदर्शित करता है। मुख्य ईवेंट लूप एकल-थ्रेडेड है (अगर यह नहीं था तो इससे कोई मतलब नहीं होगा) लेकिन नोड भारी रूप से बहु-थ्रेडेड है और आप चाहें तो मल्टी-थ्रेडेड सिंगल-प्रोसेस एप्लिकेशन लिख सकते हैं। मैं इसके बारे में एक व्यापक उत्तर लिखना पसंद करूंगा लेकिन कुछ लोगों ने आपके प्रश्न को बंद करने का फैसला किया, इसलिए मैं नहीं कर सकता। मैं इसे फिर से खोलने के लिए मतदान कर रहा हूं। यदि इसे अधिक वोट मिले और फिर से खोला गया तो कृपया टिप्पणी में मेरा उल्लेख करें।
रैप

2
@rsp आपकी टिप्पणी के लिए धन्यवाद, लेकिन मैं मुख्य सूत्र में i / o संबंधित नहीं था। यदि आप लूप के लिए एक बड़े से संबंधित कुछ सीपीयू कर रहे हैं जो कुछ करता है तो सर्वर प्रोसेसिंग कनेक्शन बंद कर देता है। अर्थ, उस समय सर्वर अनुपयोगी होता है। इसलिए हम क्लस्टर की तरह हैक्स का उपयोग करते हुए बस कुछ सरल करने के लिए छोड़ देते हैं क्योंकि यह स्वाभाविक रूप से हर कनेक्शन को फैलता है जैसे अधिकांश सर्वर करते हैं। jxcore.com ने इसे संबोधित करने की कोशिश की लेकिन फिर यह एक विशेष / संशोधित नोड प्लगइन्स का उपयोग करता है जो अनिवार्य रूप से मेरे लिए अनुपयोगी बनाता है।
foreyez

जवाबों:


292

Node.js को स्पष्ट रूप से async प्रसंस्करण में एक प्रयोग के रूप में बनाया गया था। सिद्धांत यह था कि एकल थ्रेड पर async प्रसंस्करण करना विशिष्ट थ्रेड-आधारित कार्यान्वयन की तुलना में विशिष्ट वेब लोड के तहत अधिक प्रदर्शन और मापनीयता प्रदान कर सकता है।

और क्या आपको पता है? मेरी राय में सिद्धांत का जन्म हो चुका है। एक नोड.जेएस ऐप जो सीपीयू गहन सामग्री नहीं कर रहा है वह अपाचे या आईआईएस या अन्य थ्रेड-आधारित सर्वरों की तुलना में हजारों अधिक समवर्ती कनेक्शन चला सकता है।

एकल पिरोया हुआ, async प्रकृति चीजों को जटिल बनाती है। लेकिन क्या आप ईमानदारी से सोचते हैं कि यह थ्रेडिंग की तुलना में अधिक जटिल है? एक दौड़ की स्थिति आपके पूरे महीने को बर्बाद कर सकती है! या कहीं पर कुछ सेटिंग के कारण अपने थ्रेड पूल को खाली कर दें और अपने प्रतिक्रिया समय को एक क्रॉल पर धीमी गति से देखें! गतिरोधों, प्राथमिकता वाले आक्रमणों और अन्य सभी परिवर्तनों का उल्लेख नहीं करना चाहिए जो बहुस्तरीयता के साथ चलते हैं।

अंत में, मुझे नहीं लगता कि यह सार्वभौमिक रूप से बेहतर या बदतर है; यह अलग है, और कभी-कभी यह बेहतर होता है और कभी-कभी यह नहीं होता है। इस काम के लिए सही उपकरण का उपयोग करें।


26
लेकिन वेब सर्वर आमतौर पर सीपीयू के गहन सामान का उपयोग करते हैं, यह सिर्फ डेटाबेस लाने के लिए नहीं है। हमें उस चीज़ को संसाधित करने की आवश्यकता है जो हम प्राप्त करते हैं, और ग्राहक को सेवा देने से पहले व्यापार तर्क का एक बहुत कुछ करते हैं।
foreyez

22
तो बस कार्यकर्ताओं को, अच्छी तरह से! यह Node.js. के साथ पूरी डील है भारी सामान एक अन्य प्रक्रिया में चल सकता है, और आप इसे हल्के कॉलबैक में परिणाम देते हैं।
MaiaVictor

7
इसके साथ समस्या यह है कि प्रति कार्यकर्ता एक ओएस स्तर की प्रक्रिया चल रही है .. आप उन्हें "ps" कमांड का उपयोग करके देखेंगे। ताकि संभावित रूप से एक ही बार मशीन पर चलने वाली हजारों प्रक्रियाओं का मतलब है - यह पागल है!
foreyez

9
@foreyez, आपको प्रति उपयोगकर्ता एक प्रक्रिया की आवश्यकता नहीं है। आपके पास यह विकल्प है कि आप लोड को कैसे विभाजित करते हैं। इसके अलावा, हर कोई सीपीयू गहन सामग्री का एक टन नहीं कर रहा है। नोड एक नौकरी के लिए एक उपकरण है ... शायद आपकी नौकरी नहीं है, लेकिन कई तरह की नौकरियां हैं।
ब्रैड

15
असल में, मैं @foreyez को उस कथन का समर्थन करना चाहता हूं जो "वेब सर्वर आमतौर पर सीपीयू गहन सामग्री के एलओटी (एसआईसी) के लिए है"। मेरे अनुभव में, वे नहीं हैं। या हो सकता है कि 'सीपीयू सघन' की मेरी परिभाषा उससे भिन्न हो। एक UI में उत्पाद डेटा परिवर्तित करना CPU गहन नहीं है, और न ही आदेश या पसंद की गणना कर रहा है। अधिकांश वेब बहुत ही लेन-देन वाला है। CPU सघन सामान वीडियो परिवर्तित करना, छवि प्रारूप परिवर्तित करना, आदि जैसी चीजें हैं। इनमें से अधिकांश फ़ाइल i / o के कारण है, जो वास्तव में, नोड बहुत अच्छा करता है। और इसे एक और प्रक्रिया के लिए ऑफलोड करना आसान बनाता है जो कि परिवर्तित करने के लिए समर्पित है।
पॉल

62

सर्वर के लिए "एक थ्रेड प्रति अनुरोध" मॉडल के साथ समस्या यह है कि वे इवेंट लूप थ्रेड मॉडल की तुलना में कई परिदृश्यों के लिए अच्छी तरह से स्केल नहीं करते हैं।

आमतौर पर, I / O गहन परिदृश्यों में अनुरोधों के अधिकांश समय I / O के पूरा होने का इंतजार करते हैं। इस समय के दौरान, "एक धागा प्रति अनुरोध" मॉडल में, धागे से जुड़े संसाधन (जैसे मेमोरी) अप्रयुक्त हैं और मेमोरी सीमित कारक है। इवेंट लूप मॉडल में, लूप थ्रेड हैंडल करने के लिए अगले ईवेंट (I / O समाप्त) का चयन करता है। इसलिए धागा हमेशा व्यस्त रहता है (यदि आप इसे सही ढंग से प्रोग्राम करते हैं)।

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

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

यदि आप चांदी की गोली की तलाश कर रहे हैं जो बिना किसी प्रयास के किसी भी परिदृश्य के साथ फिट होगी, तो आप अपने पैर में एक गोली के साथ समाप्त हो जाएंगे।


8
V8 मल्टीथ्रेडिंग समर्थन की कमी के कारण Node.js केवल-इवेंट प्रोसेसिंग तक ही सीमित है। अच्छी तरह से, जावास्क्रिप्ट भाषा में ही आवश्यक विशेषताओं का अभाव है, इसलिए कोई भी कार्यान्वयन अनुपात मुश्किल होगा। यह मेरी राय में, Node.js का मुख्य अपराधी है। अन्य भाषाओं में आप जो चाहें चुन सकते हैं। या दोनों मॉडल के कुछ हाइब्रिड, जैसे जावा एनआईओ।
फ़्रेमग्रेस

2
@Kazaag, आधुनिक वेब सर्वर करना एक ThreadPool बनाए रखें। वे केवल प्रति पृष्ठ लोड पर एक नया धागा स्पंदित नहीं करते हैं। वे पुराने वेब सर्वर हैं।
पचेरियर

1
@ स्पेसर मैंने कभी नहीं कहा कि एक नया धागा स्पॉन है, लेकिन प्रत्येक थ्रेड को एक अनुरोध पर आवंटित किया जाता है जब तक कि अनुरोध समाप्त नहीं हो जाता।
काजाग

2
@ कागाज निश्चित रूप से यह सामान्य नियम नहीं है कि "अनुरोध समाप्त होने तक प्रत्येक धागे को एक अनुरोध पर आवंटित किया जाता है"। I। In .Net (HTTP अनुरोधों को संसाधित करने सहित) एक को async (टास्क आधारित) प्रोग्रामिंग का उपयोग करना चाहिए और इसे पूरा करने के लिए I / O और अन्य async ऑपरेशनों की प्रतीक्षा करते हुए थ्रेड जारी करेंगे। यह उच्च स्तरीय प्रोग्रामिंग के साथ-साथ MVC / API नियंत्रकों पर लागू होता है। तो व्यवहार में 20 HTTP अनुरोध लंबित हो सकते हैं लेकिन केवल एक सक्रिय धागा।
user3285954

29

लंबी कहानी छोटी, नोड V8 से निकलती है, जो आंतरिक रूप से एकल-थ्रेडेड है। सीपीयू-गहन कार्यों के लिए बाधाओं के आसपास काम करने के तरीके हैं।

एक बिंदु (0.7) पर, लेखकों ने गणना के कई थ्रेड्स को लागू करने के तरीके के रूप में आइसोलेट्स पेश करने की कोशिश की, लेकिन अंततः हटा दिया गया: https://groups.google.com/forum/#/msg/nodejs/zLzuo292x0/F7gqfUiKi2sJ


क्या आपके पास इस "अलग" के बारे में अधिक जानकारी है?
18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.