Concurrency में महारत
कई लोग एक ही समय में आपके ऐप का उपयोग करेंगे, और आप अपने ऐप को जितनी जल्दी हो सके डिलीवर करना चाहते हैं। इसलिए आपको concurrency को संभालने के किसी तरीके की आवश्यकता होगी। डरें नहीं! अधिकांश वेब सर्वर डिफ़ॉल्ट रूप से पहले से ही ऐसा करते हैं। लेकिन जब आपको स्केल करने की आवश्यकता होती है, तो आप concurrency का यथासंभव कुशल तरीके से उपयोग करना चाहते हैं।
Concurrency के विभिन्न प्रकार
Concurrency को संभालने के कई तरीके हैं: मल्टी-प्रोसेस, मल्टी-थ्रेडिंग और इवेंट-ड्रिवन। इनमें से प्रत्येक के अपने उपयोग, फायदे और नुकसान हैं। इस लेख में, आप सीखेंगे कि वे कैसे भिन्न हैं और किसका उपयोग कब करना है।
मल्टी-प्रोसेस (Unicorn)
यह concurrency को संभालने का सबसे आसान तरीका है। एक मास्टर प्रोसेस खुद को कई वर्कर प्रोसेस में फोर्क करता है। वर्कर प्रोसेस वास्तविक अनुरोधों को संभालता है, जबकि मास्टर वर्कर्स को प्रबंधित करता है।
प्रत्येक वर्कर प्रोसेस की मेमोरी में पूरी कोडबेस होती है। यह इस विधि को काफी मेमोरी-गहन बनाता है, और बड़े इंफ्रास्ट्रक्चर में स्केल करना कठिन बनाता है।
| मल्टी-प्रोसेस सारांश | |
|---|---|
| उपयोग का मामला | एक नॉन-Ruby उदाहरण जिसे आप शायद जानते हैं वह है Chrome ब्राउज़र। यह प्रत्येक टैब को अपनी प्रक्रिया देने के लिए मल्टी-प्रोसेस concurrency का उपयोग करता है। यह एक टैब को पूरे एप्लिकेशन को नीचे लाए बिना क्रैश होने की अनुमति देता है। उनके मामले में, यह शोषण को एक टैब तक अलग करने में भी मदद करता है। |
| फायदे | कार्यान्वित करने में सबसे सरल। थ्रेड सुरक्षा के साथ कठिनाइयों को नज़रअंदाज करता है। प्रत्येक वर्कर बाकी सिस्टम को नुकसान पहुंचाए बिना क्रैश हो सकता है। |
| नुकसान | प्रत्येक प्रक्रिया पूरी कोडबेस को मेमोरी में लोड करती है। यह इसे मेमोरी-गहन बनाता है। इसलिए, यह बड़ी संख्या में समवर्ती कनेक्शन के लिए स्केल नहीं करता। |
मल्टी-थ्रेडिंग (Puma)
यह थ्रेडिंग मॉडल एक प्रक्रिया को एक ही समय में कई अनुरोधों को संभालने की अनुमति देता है। यह एक ही प्रक्रिया के भीतर कई थ्रेड्स चलाकर ऐसा करता है।
मल्टी-प्रोसेस दृष्टिकोण के विपरीत, सभी थ्रेड्स एक ही प्रक्रिया के भीतर चलते हैं। इसका मतलब है कि वे ग्लोबल वेरिएबल्स जैसे डेटा साझा करते हैं। इसलिए, प्रति थ्रेड केवल मेमोरी के छोटे टुकड़ों का उपयोग किया जाता है।
ग्लोबल इंटरप्रेटर लॉक
यह हमें MRI में ग्लोबल इंटरप्रेटर लॉक (GIL) पर लाता है। GIL सभी Ruby कोड के निष्पादन के चारों ओर एक लॉक है। भले ही हमारे थ्रेड्स समानांतर में चलते दिखाई देते हैं, किसी भी समय केवल एक थ्रेड सक्रिय होता है।
IO GIL के बाहर संचालित होता है। जब आप एक डेटाबेस क्वेरी निष्पादित करते हैं और परिणाम की प्रतीक्षा करते हैं, तो यह लॉक नहीं करेगा। एक अन्य थ्रेड को इस बीच कुछ काम करने का मौका मिलेगा। यदि आप थ्रेड्स में बहुत सारे गणित और हैश या सरणियों पर ऑपरेशन करते हैं, तो यदि आप MRI का उपयोग करते हैं तो आप केवल एक कोर का उपयोग करेंगे। ज्यादातर मामलों में आपको अभी भी अपनी मशीन का पूरी तरह से उपयोग करने के लिए कई प्रक्रियाओं की आवश्यकता होती है। या आप Rubinius या jRuby का उपयोग कर सकते हैं, जिनमें GIL नहीं है।
थ्रेड सुरक्षा
यदि आप कई थ्रेड्स का उपयोग करते हैं तो आपको साझा डेटा में हेरफेर करने वाले सभी कोड को थ्रेड-सुरक्षित तरीके से लिखने के लिए सावधान रहना होगा। आप इसे उदाहरण के लिए साझा डेटा संरचनाओं को हेरफेर करने से पहले Mutex का उपयोग करके लॉक करके कर सकते हैं। यह सुनिश्चित करेगा कि अन्य थ्रेड्स आपके डेटा को बदलते समय पुराने डेटा पर अपना काम आधारित नहीं कर रहे हैं।
| मल्टी-थ्रेडेड सारांश | |
|---|---|
| उपयोग का मामला | यह "मध्यम मार्ग" विकल्प है। बहुत सारे मानक वेब एप्लिकेशन के लिए उपयोग किया जाता है जिन्हें छोटे अनुरोधों के भार को संभालना चाहिए (जैसे एक व्यस्त वेब एप्लिकेशन)। |
| फायदे | मल्टी-प्रोसेस की तुलना में कम मेमोरी का उपयोग करता है। |
| नुकसान | आपको यह सुनिश्चित करना होगा कि आपका कोड थ्रेड-सुरक्षित है। यदि कोई थ्रेड क्रैश का कारण बनता है, तो यह संभावित रूप से आपकी प्रक्रिया को नीचे ले जा सकता है। GIL I/O को छोड़कर सभी ऑपरेशन को लॉक करता है। |
इवेंट-लूप (Thin)
इवेंट-लूप्स का उपयोग तब किया जाता है जब आपको बहुत सारे समवर्ती I/O ऑपरेशन करने की आवश्यकता होती है। मॉडल स्वयं एक ही समय में कई अनुरोधों को निष्पादित करने के लिए मजबूर नहीं करता है, लेकिन यह बहुत सारे समवर्ती उपयोगकर्ताओं को संभालने का एक कुशल तरीका है।
नीचे आप Ruby में लिखा गया एक बहुत सरल इवेंट लूप देखेंगे। लूप event_queue से इवेंट लेगा और उसे संभालेगा। यदि कोई इवेंट नहीं है, तो यह सोएगा और यह देखने के लिए दोहराएगा कि कतार में नए इवेंट हैं या नहीं।
loop do
if event_queue.any?
handle_event(event_queue.pop)
else
sleep 0.1
end
end
चित्रित संस्करण
इस चित्रण में, हम इसे एक कदम आगे ले जा रहे हैं। इवेंट लूप अब OS, कतार और कुछ मेमोरी के साथ एक सुंदर नृत्य करता है।
चरण दर चरण
- OS नेटवर्क और डिस्क उपलब्धता को ट्रैक करता है।
- जब OS देखता है कि I/O तैयार है, तो यह कतार में एक इवेंट भेजता है।
- कतार इवेंट्स की एक सूची है जिससे इवेंट लूप शीर्ष वाला लेता है।
- इवेंट लूप इवेंट को संभालता है।
- यह कनेक्शन के बारे में मेटा डेटा स्टोर करने के लिए कुछ मेमोरी का उपयोग करता है।
- यह सीधे इवेंट कतार में एक नया इवेंट भेज सकता है। उदाहरण के लिए, इवेंट की सामग्री के आधार पर कतार को बंद करने का संदेश।
- यदि यह I/O ऑपरेशन करना चाहता है, तो यह OS को बताता है कि यह एक विशिष्ट I/O ऑपरेशन में रुचि रखता है। OS नेटवर्क और डिस्क को ट्रैक करता है (चरण [1] देखें) और जब I/O तैयार होता है तो फिर से एक इवेंट जोड़ता है।
| इवेंट-लूप सारांश | |
|---|---|
| उपयोग का मामला | अपने उपयोगकर्ताओं के लिए बहुत सारे समवर्ती कनेक्शन का उपयोग करते समय। Slack जैसी सेवाओं के बारे में सोचें। Chrome नोटिफिकेशन। |
| फायदे | प्रति कनेक्शन लगभग कोई मेमोरी ओवरहेड नहीं। बहुत बड़ी संख्या में समानांतर कनेक्शन तक स्केल करता है। |
| नुकसान | यह समझने के लिए एक कठिन मानसिक मॉडल है। बैच साइज़ छोटे और अनुमानित होने चाहिए ताकि कतारें न बनें। |
आपको किसका उपयोग करना चाहिए?
हमें उम्मीद है कि इस लेख ने आपको विभिन्न concurrency मॉडल की बेहतर समझ दी है। यह डेवलपर के रूप में समझने के लिए अधिक कठिन विषय वस्तु में से कुछ है, लेकिन इसे समझने से आपको अपने ऐप के लिए सही सेटअप का प्रयोग और उपयोग करने के उपकरण मिलेंगे।
सारांश में
- अधिकांश ऐप्स के लिए थ्रेडिंग समझ में आता है, Ruby/Rails इकोसिस्टम धीरे-धीरे इस दिशा में आगे बढ़ रहा है।
- यदि आप लंबे समय तक चलने वाली स्ट्रीम के साथ अत्यधिक समवर्ती ऐप्स चलाते हैं, तो इवेंट-लूप आपको स्केल करने की अनुमति देता है।
- यदि आपके पास उच्च ट्रैफिक साइट नहीं है, या आप अपने वर्कर्स के टूटने की उम्मीद करते हैं तो अच्छे पुराने मल्टी-प्रोसेस के लिए जाएं।
और, एक इवेंट लूप को एक थ्रेड के अंदर, एक मल्टी-प्रोसेस सेटअप के अंदर चलाना संभव है। तो हाँ, आप अपना स्ट्रॉपवाफेल खा सकते हैं और उसे पा भी सकते हैं!
यदि आप इन concurrency मॉडल के बारे में अधिक पढ़ना चाहते हैं तो मल्टी-प्रोसेस, मल्टी-थ्रेडिंग और इवेंट लूप पर हमारे विस्तृत लेख देखें।