प्रतिनिधि इंटरव्यू विषय

प्रोसेस और थ्रेड के बीच क्या अंतर है?

सामान्यमध्यम
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक एप्लिकेशन को 8 CPU-बाउंड थर्ड-पार्टी प्लगइन्स चलाने हैं जो क्रैश या हैंग हो सकते हैं, और साथ ही अधिकतम 2,000 समवर्ती (concurrent) I/O-बाउंड रिक्वेस्ट्स को प्रोसेस करना है जो एक बड़े मुख्य रूप से रीड-ओनली (read-mostly) कैश को साझा करते हैं। क्या आप प्रत्येक वर्कलोड के लिए प्रोसेस, थ्रेड या किसी अन्य कंकरेंसी मॉडल का उपयोग करेंगे, और क्यों?

प्रश्न और इसका उपयोग कब करें

एक एप्लिकेशन को 8 CPU-बाउंड थर्ड-पार्टी प्लगइन्स चलाने हैं जो क्रैश या हैंग हो सकते हैं, और साथ ही अधिकतम 2,000 समवर्ती (concurrent) I/O-बाउंड रिक्वेस्ट्स को प्रोसेस करना है जो एक बड़े मुख्य रूप से रीड-ओनली कैश को साझा करते हैं। प्रोसेस और थ्रेड के बीच अंतर स्पष्ट करें, फिर प्रत्येक वर्कलोड के लिए एक एक्ज़ीक्यूशन मॉडल चुनें। इसमें रिसोर्स ओनरशिप, शेड्यूलिंग, कम्युनिकेशन, सिंक्रोनाइज़ेशन, विफलता और सुरक्षा आइसोलेशन, लाइफसाइकिल और वैलिडेशन को कवर करें।

यह सॉफ्टवेयर, बैकएंड, इंफ्रास्ट्रक्चर और सिस्टम्स भूमिकाओं के लिए ऑपरेटिंग-सिस्टम के बुनियादी सिद्धांतों से संबंधित प्रश्न है। 8 और 2,000 की संख्याएं साक्षात्कार के लिए मानी गई स्थितियां हैं, कोई सार्वभौमिक साइज़िंग नियम नहीं हैं। पहला वर्कलोड आइसोलेशन और CPU पैरेललिज्म को प्राथमिकता देता है; दूसरा उच्च I/O कंकरेंसी और साझा डेटा तक कुशल पहुंच को महत्व देता है। एक उपयोगी उत्तर प्रोसेस या थ्रेड को सीधे तौर पर तेज़ बताने के बजाय इन बाधाओं के आधार पर दो विकल्प निकालता है।

इंटरव्यूअर क्या मूल्यांकन कर रहा है

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

दूसरा संकेत यह है कि उम्मीदवार कंकरेंसी को पैरेललिज्म से अलग समझता है या नहीं। कई कार्य एक ही कोर पर इंटरलीविंग के माध्यम से समवर्ती रूप से आगे बढ़ सकते हैं। वे समानांतर (parallel) रूप से केवल तभी निष्पादित होते हैं जब रनटाइम और ऑपरेटिंग सिस्टम उन्हें कई कोर पर चलाते हैं। 2,000 थ्रेड्स बनाने से 2,000-तरफा CPU पैरेललिज्म नहीं बनता है, और आठ CPU-बाउंड कार्यों का अर्थ यह नहीं है कि आठ वर्कर प्रोसेस मशीन के CPU और मेमोरी बजट में फिट हो जाएंगे।

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

उत्तर देने से पहले स्पष्ट करने योग्य प्रश्न

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

30-सेकंड का उत्तर ढांचा

"एक प्रोसेस एक अलग वर्चुअल एड्रेस स्पेस और प्रोसेस-व्यापी रिसोर्सेज का मालिक होता है; इसमें एक या अधिक थ्रेड्स होते हैं। थ्रेड्स शेड्यूलेबल एक्ज़ीक्यूशन संदर्भ होते हैं जो उस प्रोसेस की स्थिति को साझा करते हैं लेकिन अपना स्वयं का स्टैक, रजिस्टर्स, आइडेंटिफ़ायर और थ्रेड-लोकल स्थिति बनाए रखते हैं। मैं क्रैश की संभावना वाले CPU प्लगइन्स को सुपरवाइज़्ड, रिसोर्स-सीमित प्रोसेस में चलाऊंगा ताकि होस्ट हीप को साझा किए बिना किसी खराबी या हैंग होने पर उन्हें समाप्त और प्रतिस्थापित किया जा सके; वर्कर की संख्या CPU और मेमोरी बजट के अनुसार तय होगी, न कि स्वचालित रूप से आठ। 2,000 मुख्य रूप से प्रतीक्षा करने वाली रिक्वेस्ट्स के लिए, यदि संपूर्ण डिपेंडेंसी पाथ नॉन-ब्लॉकिंग है तो मैं एक async इवेंट लूप का उपयोग करूंगा, या यदि लाइब्रेरीज़ ब्लॉक होती हैं तो एक सीमित थ्रेड पूल का उपयोग करूंगा। थ्रेड्स मुख्य रूप से रीड-ओनली कैश को साझा कर सकते हैं, विशेष रूप से इम्यूटैबल स्नैपशॉट के रूप में। निर्णय लेने से पहले मैं थ्रूपुट, p99, मेमोरी, कॉन्टेक्स्ट स्विच, IPC या लॉक वेट को बेंचमार्क करूंगा, और क्रैश, हैंग व रेस कंडीशंस को इंजेक्ट करके परीक्षण करूंगा।"

चरण-दर-चरण समाधान

चरण 1: ओनरशिप मॉडल का निर्माण करें

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

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

"डिफ़ॉल्ट रूप से अलग" होना महत्वपूर्ण है। प्रोसेस जानबूझकर मेमोरी, फाइल्स और हैंडल्स साझा कर सकते हैं; थ्रेड्स मनमाने शेयर्ड म्यूटेशन के बजाय कतारों (queues) के माध्यम से संवाद कर सकते हैं। यह विकल्प डिफ़ॉल्ट विफलता और ओनरशिप सीमा को नियंत्रित करता है, न कि एकमात्र संभावित कम्युनिकेशन API को।

चरण 2: कंकरेंसी, पैरेललिज्म और लागत को अलग करें

कंकरेंसी का अर्थ है कि कार्य की कई इकाइयां प्रगति में हैं। पैरेललिज्म का अर्थ है कि कार्य अलग-अलग प्रोसेसिंग रिसोर्सेज पर एक ही क्षण में निष्पादित होता है। एक थ्रेड कई एसिंक्रोनस I/O ऑपरेशंस को मल्टीप्लेक्स कर सकता है; कई निष्पादन योग्य थ्रेड्स या प्रोसेस कई कोर का उपयोग कर सकते हैं। वास्तविक CPU पैरेललिज्म उपलब्ध कोर, कंटेनर कोटा और रनटाइम व्यवहार द्वारा सीमित होता है।

थ्रेड्स को बनाना और उनके बीच स्विच करना आमतौर पर सस्ता होता है क्योंकि वे एक ही एड्रेस स्पेस का पुन: उपयोग करते हैं, जबकि प्रोसेस आमतौर पर अधिक मेमोरी और लाइफसाइकिल स्थिति रखते हैं। यह एक सामान्य दिशा है, प्रदर्शन की गारंटी नहीं। कॉपी-ऑन-राइट प्रोसेस निर्माण, थ्रेड स्टैक रिज़र्वेशन, कैश मिसेस, एड्रेस-स्पेस परिवर्तन, रनटाइम शेड्यूलिंग, IPC पेलोड्स और लॉक विवाद किसी विशेष वर्कलोड के लिए प्रमुख लागत को उलट सकते हैं। कोई सार्वभौमिक माइक्रोसेकंड या मेमोरी संख्या न जोड़ें; लक्षित रनटाइम और प्लेटफ़ॉर्म पर मापें।

चरण 3: कम्युनिकेशन और शुद्धता (correctness) की लागतों की तुलना करें

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

प्रोसेस सामान्यतः पाइप्स, सॉकेट्स, कतारों या RPC के माध्यम से संदेशों का आदान-प्रदान करते हैं। यह एक स्पष्ट प्रोटोकॉल बनाता है और ओनरशिप का ऑडिट करना आसान बनाता है, लेकिन इसकी लागत सीरियलाइज़ेशन, कॉपी करने, बैकप्रेशर और आंशिक-विफलता से निपटने के रूप में होती है। शेयर्ड मेमोरी कॉपी करने से बच सकती है, लेकिन फिर प्रोसेस को फिर से वर्ज़निंग और सिंक्रोनाइज़ेशन प्रोटोकॉल की आवश्यकता होती है। IPC कंकरेंसी बग्स को समाप्त नहीं करता है; यह उन्हें मैसेज आइडेंटिटी, ऑर्डरिंग, पुनः प्रयास (retry), टाइमआउट और लाइफसाइकिल सीमाओं पर स्थानांतरित कर देता है।

चरण 4: प्लगइन वर्कलोड के लिए सुपरवाइज़्ड प्रोसेस चुनें

8 CPU-बाउंड थर्ड-पार्टी कार्यों के लिए, होस्ट द्वारा पर्यवेक्षित (supervised) एक सीमित प्रोसेस-वर्कर पूल का उपयोग करें। प्रत्येक कार्य को एक आइडेंटिफ़ायर, इनपुट अनुबंध, डेडलाइन, आउटपुट अनुबंध और कैंसलेशन व्यवहार दें। जो वर्कर बाहर निकलता है, अपनी डेडलाइन पार करता है या रिसोर्स सीमा का उल्लंघन करता है, उसे समाप्त और प्रतिस्थापित किया जाता है; सुपरवाइज़र तय करता है कि कार्य का पुनः प्रयास करना सुरक्षित है या नहीं। प्लगइन स्थिति को होस्ट हीप से बाहर रखें और स्पष्ट इनपुट और आउटपुट पास करें।

पूल का आकार CPU कोटा, प्लगइन मेमोरी और सर्विस हेडरूम से तय होता है। चार-कोर के कोटा पर, आठ स्थायी रूप से चलने योग्य वर्कर शुरू करने से कुल CPU कार्य को कम किए बिना कॉन्टेक्स्ट स्विचिंग बढ़ सकती है। यदि प्लगइन्स को एक बड़े सामान्य रीड-ओनली डेटा सेट की आवश्यकता है, तो वर्कर्स में एक मान्य रीड-ओनली स्नैपशॉट मैप करें या एक समर्पित डेटा सेवा चलाएं; केवल एक संभावित कॉपी से बचने के लिए फॉल्ट आइसोलेशन को न छोड़ें।

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

चरण 5: रिक्वेस्ट्स के लिए async I/O या सीमित थ्रेड पूल चुनें

अधिकतम 2,000 समवर्ती रिक्वेस्ट्स के लिए जो अपना अधिकांश समय प्रतीक्षा में बिताती हैं, "एक रिक्वेस्ट" को सीधे "एक नए प्रोसेस" में मैप न करें। यदि नेटवर्क, डेटाबेस और क्लाइंट लाइब्रेरीज़ शुरू से अंत तक नॉन-ब्लॉकिंग हैं, तो एक इवेंट लूप कम संख्या में थ्रेड्स पर कई इन-फ़्लाइट रिक्वेस्ट्स को बनाए रख सकता है। CPU-गहन कार्य को इवेंट लूप से बाहर निकालना चाहिए, और प्रत्येक कतार को एक सीमा की आवश्यकता होती है ताकि ओवरलोड अनियंत्रित मेमोरी वृद्धि के बजाय रिजेक्शन या बैकप्रेशर बन जाए।

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

चरण 6: माप और फॉल्ट इंजेक्शन के साथ निर्णय को मान्य करें

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

हैप्पी पाथ की तरह ही सीमाओं का भी आक्रामक रूप से परीक्षण करें:

  1. एक प्लगइन को क्रैश करें और सत्यापित करें कि होस्ट और अन्य वर्कर उपलब्ध रहते हैं, एग्जिट को देखा जाता है, और रीस्टार्ट नीति सीमित है।
  2. एक प्लगइन को हैंग करें और डेडलाइन, समाप्ति, क्लीनअप और पुनः प्रयास के निर्णय को सत्यापित करें।
  3. प्लगइन मेमोरी और लॉग वृद्धि के लिए बाध्य करें और सत्यापित करें कि कोटा होस्ट की सुरक्षा करता है।
  4. समवर्ती कैश रीड्स और रिफ्रेश पर दबाव डालें; जब रनटाइम प्रदान करे तो रेस डिटेक्टर का उपयोग करें और सत्यापित करें कि पाठकों को पूरा पुराना या नया स्नैपशॉट दिखाई दे।
  5. रिक्वेस्ट हैंडलिंग को संतृप्त (saturate) करें और सीमित कतारों, कैंसलेशन, डाउनस्ट्रीम सीमाओं और ओवरलोड प्रतिक्रियाओं को सत्यापित करें।
  6. सेवा को पुनरारंभ करें और सत्यापित करें कि इन-फ़्लाइट ओनरशिप अनुबंध के अनुसार या तो पुनर्प्राप्त की गई है या विफल हुई है।

पुन: प्रयोज्य निर्णय नियम यह है: जब आइसोलेशन, स्वतंत्र लाइफसाइकिल या रनटाइम CPU पैरेललिज्म प्रमुख हो तो प्रोसेस सीमा चुनें; जब इन-प्रोसेस स्थिति तक कम लागत वाली पहुंच प्रमुख हो और सिंक्रोनाइज़ेशन प्रबंधनीय रहे तो शेयर्ड थ्रेड्स चुनें; जब प्रतीक्षा कंकरेंसी प्रमुख हो और डिपेंडेंसी चेन नॉन-ब्लॉकिंग कैंसलेशन का समर्थन करती हो तो async टास्क चुनें। केवल पीक थ्रूपुट ही नहीं, उस सीमा को मान्य करें जो विफल हो सकती है।

एक मजबूत उत्तर का उदाहरण

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

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

2,000 मुख्य रूप से I/O-वेटिंग रिक्वेस्ट्स के लिए, मैं लाइब्रेरीज़ का निरीक्षण करूंगा। एक नॉन-ब्लॉकिंग पाथ के साथ मैं एक इवेंट लूप का उपयोग करूंगा और CPU कार्य को एक सीमित पूल में ले जाऊंगा। ब्लॉकिंग डिपेंडेंसीज़ के साथ मैं एक सीमित थ्रेड पूल का उपयोग करूंगा। मुख्य रूप से रीड-ओनली कैश एक इम्यूटैबल वर्शनयुक्त स्नैपशॉट होगा जिसे एटॉमिक रूप से प्रकाशित किया जाएगा, जिससे प्रत्येक रीड पर लॉक लगाने से बचा जा सकेगा। प्रत्येक कतार और डाउनस्ट्रीम कॉल की एक डेडलाइन और क्षमता सीमा होगी।

मैं CPU, मेमोरी, कतार समय, कॉन्टेक्स्ट स्विच, IPC या लॉक वेट, और इवेंट-लूप लैग के साथ-साथ थ्रूपुट और p99 की तुलना करूंगा। फिर मैं प्लगइन्स को क्रैश, हैंग और मेमोरी-स्ट्रेस करूंगा और कैश रिफ्रेश में रेस कंडीशन पैदा करूंगा। डिज़ाइन तभी सफल माना जाएगा जब इसके आइसोलेशन और शुद्धता के दावे उन विफलताओं को झेल सकें, न कि केवल इसलिए कि थ्रेड्स या प्रोसेस को आम तौर पर हल्का कहा जाता है।"

सामान्य गलतियां

  • यह कहना कि प्रोसेस एक प्रोग्राम है और थ्रेड एक फ़ंक्शन है → यह रिसोर्स ओनरशिप और शेड्यूलेबल स्थिति को छोड़ देता है → प्रोसेस की एड्रेस-स्पेस सीमा और थ्रेड की शेयर्ड व प्राइवेट एक्ज़ीक्यूशन स्थिति का वर्णन करें।
  • यह दावा करना कि थ्रेड्स सब कुछ साझा करते हैं → प्रत्येक थ्रेड का अपना स्टैक, रजिस्टर्स, आइडेंटिफ़ायर और थ्रेड-लोकल स्थिति होती है → प्रोसेस-व्यापी और प्रति-थ्रेड स्थिति को अलग-अलग सूचीबद्ध करें।
  • यह दावा करना कि प्रोसेस मेमोरी साझा नहीं कर सकते → स्पष्ट शेयर्ड मैपिंग संभव है → बताएं कि प्रोसेस डिफ़ॉल्ट रूप से अलग होते हैं और सुरक्षित रूप से साझा करने के लिए आवश्यक प्रोटोकॉल की व्याख्या करें।
  • कंकरेंसी और पैरेललिज्म को पर्यायवाची कहना → कार्य एक साथ निष्पादित हुए बिना एक कोर पर इंटरलीव हो सकता है → पैरेललिज्म को कोर, कोटा और रनटाइम व्यवहार से जोड़ें।
  • आठ कार्य होने के कारण आठ वर्कर्स का चयन करना → निष्पादन योग्य वर्कर सीमित CPU और मेमोरी के लिए प्रतिस्पर्धा करते हैं → कोटा, माप और सर्विस हेडरूम के आधार पर पूल का आकार तय करें।
  • अविश्वसनीय कोड के लिए प्रोसेस को पूर्ण सैंडबॉक्स के रूप में उपयोग करना → एक प्रोसेस अभी भी अनुमत फाइल्स, नेटवर्क और कर्नेल इंटरफेस तक पहुंच सकता है या रिसोर्सेज को समाप्त कर सकता है → न्यूनतम प्रिविलेज, सैंडबॉक्स नीति, कोटा और आउटपुट वैलिडेशन जोड़ें।
  • बिना किसी सीमा के प्रत्येक प्रतीक्षारत रिक्वेस्ट के लिए एक थ्रेड बनाना → स्टैक मेमोरी, शेड्यूलिंग और डाउनस्ट्रीम कॉल्स सेवा को समाप्त कर सकती हैं → async I/O या बैकप्रेशर के साथ मापे गए सीमित पूल का उपयोग करें।
  • ओनरशिप नियम के बिना एक म्युटेबल कैश साझा करना → डेटा रेस और लॉक विवाद शुद्धता या टेल लेटेंसी को बाधित कर सकते हैं → इम्यूटैबल स्नैपशॉट को प्राथमिकता दें या सिंक्रोनाइज़ेशन को परिभाषित और परीक्षण करें।
  • केवल औसत थ्रूपुट की तुलना करना → एक डिज़ाइन p99 कतार, मेमोरी वृद्धि, या कमजोर आइसोलेशन को छिपा सकता है → लेटेंसी वितरण को मापें और क्रैश, हैंग, संतृप्ति और रेस कंडीशंस को इंजेक्ट करें।
  • यह मान लेना कि थ्रेड्स हमेशा तेज़ होते हैं → रनटाइम, IPC, कैश, लॉक और वर्कलोड की लागतें भिन्न होती हैं → कम ओवरहेड को एक परिकल्पना मानें और वास्तविक कार्यान्वयन को बेंचमार्क करें।

फॉलो-अप प्रश्न और उत्तर

फॉलो-अप 1: क्या प्रोसेस अभी भी 20 GB के रीड-ओनली मॉडल को साझा कर सकते हैं?

हाँ। प्रत्येक वर्कर में एक मान्य, इम्यूटैबल फाइल या शेयर्ड-मेमोरी क्षेत्र को रीड-ओनली के रूप में मैप करें ताकि जहां ऑपरेटिंग सिस्टम समर्थन करता है वहां फिजिकल पेजों को साझा किया जा सके। मैपिंग को वर्शनयुक्त करें और इन-प्लेस संशोधित करने के बजाय वर्कर्स को एक नए स्नैपशॉट पर स्विच करें। पेज-फॉल्ट और रेजिडेंसी व्यवहार को मापें, और प्रति-रिक्वेस्ट म्युटेबल स्थिति को शेयर्ड क्षेत्र से बाहर रखें।

फॉलो-अप 2: यदि लैंग्वेज रनटाइम CPU-बाउंड थ्रेड्स को सीरियलाइज़ करता है तो क्या बदलता है?

सटीक रनटाइम और वर्कलोड की पुष्टि करें; एक लॉक केवल प्रबंधित-भाषा (managed-language) निष्पादन को कवर कर सकता है जबकि नेटिव लाइब्रेरीज़ इसे छोड़ देती हैं। यदि CPU कार्य सीरियलाइज़्ड है, तो वर्कर प्रोसेस या रनटाइम सुविधा का उपयोग करें जो सही समानांतर निष्पादन प्रदान करती है। सीमित कतारों और कैंसलेशन को बनाए रखें, क्योंकि वर्कर प्रिमिटिव को बदलने से ओवरलोड की समस्या हल नहीं होती है।

फॉलो-अप 3: क्या एक ब्लॉक हुआ थ्रेड पूरे प्रोसेस को रोक देता है?

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

फॉलो-अप 4: थ्रेड पूल इवेंट लूप से बेहतर कब होता है?

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

फॉलो-अप 5: आप एक वर्कर क्रैश को रीस्टार्ट स्टॉर्म बनने से कैसे रोकते हैं?

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

फॉलो-अप 6: अलग-अलग सेवाओं को स्थानीय प्रोसेस की जगह कब लेनी चाहिए?

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

सार्वजनिक स्रोत

संबंधित प्रश्न