यह पोस्ट कॉलिन वेल्ड और कॉनर एडम्स द्वारा लिखी गई है। इसे यहाँ पढ़ें या [हमारे ब्लॉग पर](https://modal.com/blog/scaling-to-1-million-concurrent-sandboxes-in-seconds) पढ़ें।
Modal में, हम अन्य चीजों के अलावा सैंडबॉक्स बनाते हैं। एजेंट सैंडबॉक्स में चलते हैं, और एजेंट सॉफ्टवेयर को खा रहे हैं। आज, Modal प्रतिदिन लाखों सैंडबॉक्स चलाता है, प्रति ग्राहक पचास हज़ार तक एक साथ सैंडबॉक्स सपोर्ट करता है, और रीइन्फोर्समेंट लर्निंग से लेकर बैकग्राउंड एजेंट तक, विभिन्न उपयोग मामलों को बड़े पैमाने पर सपोर्ट करता है।
तेज़ी से, हमारे उपयोगकर्ताओं को अधिक से अधिक सैंडबॉक्स की आवश्यकता होती है, जो उच्च दरों पर बनाए जाते हैं। रीइन्फोर्समेंट लर्निंग के लिए लाखों सैंडबॉक्स को एक साथ चलाने की आवश्यकता हो सकती है, और रोलआउट की शुरुआत में सैकड़ों हज़ारों सैंडबॉक्स का बर्स्ट बनाना पड़ सकता है। इसी तरह, ट्रैफिक बर्स्ट से निपटने के लिए एजेंटों को तेजी से बड़े पैमाने और उच्च एक साथ निर्माण दरों की आवश्यकता होती है।
हमारा मौजूदा सैंडबॉक्स प्लेटफॉर्म वास्तव में अच्छा है, लेकिन इसे इन पैमानों के लिए डिज़ाइन नहीं किया गया था; न ही कोई अन्य मौजूदा समाधान है। हम स्केल और प्रदर्शन के प्रति जुनूनी हैं, और हम चाहते हैं कि हमारा इंफ्रास्ट्रक्चर एजेंटों के विकास को गति दे, न कि घर्षण बढ़ाए। इसलिए हम वापस ड्रॉइंग बोर्ड पर गए।
पिछले कुछ महीनों में, हमने अपने कोर सैंडबॉक्स प्लेटफॉर्म को स्केल और विश्वसनीयता दोनों के लिए नए सिरे से बनाया है। हमारे नए सिस्टम पर, उपयोगकर्ता लाखों सैंडबॉक्स को एक साथ चला सकते हैं और प्रति सेकंड दसियों हज़ार सैंडबॉक्स बना सकते हैं। हमने अपने कंट्रोल प्लेन से सभी केंद्रीय बाधाओं को हटा दिया है ताकि कोई व्यावहारिक स्केलिंग सीमाएं न हों, और हमने कंटेनर शेड्यूलिंग और स्टार्टअप के हर हिस्से को ऑप्टिमाइज़ किया है, शेड्यूलिंग पथ को लोड बैलेंसर्स की एक परत तक सरल बनाते हुए, जो सीधे हमारे वर्कर फ्लीट पर कंटेनर बनाते हैं।
हमारे प्लेटफॉर्म की क्षमता के प्रदर्शन के रूप में, हमने एक साथ दस लाख सैंडबॉक्स चलाए हैं, सभी 1 मिलियन को एक मिनट से भी कम समय में बनाते हुए।

सबूत है कि हम बहुत सारे सैंडबॉक्स चला सकते हैं।
अधिकांश समाधान क्यों स्केल नहीं करते
1 मिलियन सैंडबॉक्स चलाना किसी भी कंटेनर प्लेटफॉर्म की सीमाओं को धकेलता है, कंटेनरों की विशाल संख्या के कारण ही नहीं, बल्कि इसलिए भी कि इतने सारे सैंडबॉक्स चलाने के लिए दसियों हज़ार कंप्यूट नोड्स की आवश्यकता होती है। ऐसे कई ऑपरेशन होंगे जो या तो O(कंटेनर) हैं, या O(नोड्स) हैं, या दोनों, जो पारंपरिक कंटेनर प्लेटफॉर्म को स्केलिंग सीमाओं से टकराने का कारण बनेंगे।
Kubernetes के लिए, एक उदाहरण के रूप में:
- शेड्यूलिंग एल्गोरिथ्म सबसे खराब स्थिति में n नोड्स और p पॉड्स के लिए O(n x p) है, और शेड्यूलिंग डिफ़ॉल्ट रूप से सीरियलाइज़्ड है।
- प्रत्येक पॉड अपने जीवनकाल में केंद्रीय Kubernetes ड्यूरेबल स्टोर etcd में कई राइट्स का कारण बनता है, जो उच्च पॉड निर्माण दरों या उच्च पॉड चर्न के तहत गंभीर समस्याएं पैदा कर सकता है, और etcd किसी कीस्पेस के भीतर मूल रूप से शार्डेबल नहीं है।
- प्रत्येक नोड को लाइवनेस सिग्नल करने के लिए प्रति हार्टबीट अंतराल में कम से कम एक बार etcd में लिखना चाहिए, इसलिए बेसलाइन etcd राइट लोड पॉड निर्माण से पूरी तरह स्वतंत्र O(नोड्स) है।

Kubernetes शेड्यूलिंग फ्लो का अनुमान। नए पॉड्स API सर्वर द्वारा etcd (एक मजबूत सुसंगत ड्यूरेबल स्टोर) में लिखे जाते हैं। Kubernetes शेड्यूलर नए अनअसाइन किए गए पॉड्स के लिए देखता है, और उन्हें API सर्वर को कॉल करके नोड्स को असाइन करता है, जो फिर से etcd में लिखता है; इस राइट के बाद, एक नोड पॉड शुरू कर सकता है।
Kubernetes को स्केल किया जा सकता है, लेकिन इसके लिए गंभीर काम की आवश्यकता होती है। बड़ी संख्या में नोड्स चलाने के लिए, etcd को आमतौर पर फिर से लिखा जाना चाहिए या बदला जाना चाहिए। उच्च शेड्यूलिंग थ्रूपुट का समर्थन करने के लिए शेड्यूलिंग एल्गोरिथ्म को समानांतर करने के लिए एक जटिल स्कैटर-गैदर सिस्टम बनाने की आवश्यकता होती है, जबकि पॉड स्थिति के लिए सत्य का एकल स्रोत बनाए रखना होता है। शार्डिंग और समानांतरीकरण डिफ़ॉल्ट रूप से आसान नहीं है, क्योंकि Kubernetes अपने डिज़ाइन की रीढ़ के रूप में मजबूत संगति पर निर्भर करता है।
Modal की मूल सैंडबॉक्स आर्किटेक्चर में समान समस्याएं हैं। Kubernetes की तरह, हम अपने बैकएंड में मजबूत संगति पर भरोसा करते हैं, इसलिए सैंडबॉक्स बनाने और शेड्यूल करने के लिए वैश्विक समन्वय और Postgres में O(सैंडबॉक्स) राइट्स की आवश्यकता होती है, जिसे हम आसानी से शार्ड नहीं कर सकते।

Modal की मूल सैंडबॉक्स कंट्रोल प्लेन आर्किटेक्चर। जब सैंडबॉक्स बनाए जाते हैं, तो उन्हें एक कतार पर रखा जाता है और Postgres में लिखा जाता है। शेड्यूलिंग आशावादी है और समानांतर में चलती है, जिसमें विरोधों से बचने के लिए केंद्रीय समन्वय की आवश्यकता होती है। एक सैंडबॉक्स को वर्कर (कंप्यूट नोड) को असाइन करने के लिए Postgres में एक अतिरिक्त राइट की आवश्यकता होती है।
क्योंकि हम Kubernetes पर निर्माण नहीं करते हैं, हम इस सिस्टम के कई हिस्सों को स्केल आउट करने में सक्षम रहे हैं। उदाहरण के लिए, शेड्यूलिंग डिफ़ॉल्ट रूप से समानांतर है, जो हमें बहुत उच्च बर्स्ट सैंडबॉक्स निर्माण दर प्राप्त करने की अनुमति देता है। लेकिन जैसे-जैसे हम बड़ी और बड़ी संख्या में नोड्स और सैंडबॉक्स की ओर बढ़े, हमें लगातार नई बाधाओं का सामना करना पड़ा जो O(सैंडबॉक्स) या O(नोड्स) थीं, लेकिन स्केल आउट करना आसान नहीं था।
उदाहरण के लिए, हम प्रत्येक सैंडबॉक्स के लिए एक ड्यूरेबल वर्कफ़्लो चलाते हैं जो समाप्त होता है, इसलिए उच्च सैंडबॉक्स चर्न दरें बड़ी इवेंट बैकलॉग बनाएंगी। हम बार-बार ऐसे RPCs में भागते थे जो O(सैंडबॉक्स) की दर से कॉल किए जाते थे, जो हमारे सिस्टम में अप्रत्याशित लोड समस्याओं का कारण बनते थे। और बड़ी संख्या में सैंडबॉक्स चलाने के लिए आवश्यक नोड्स की विशाल संख्या ने नोड प्रबंधन और ऑटोस्केलिंग में कई डाउनस्ट्रीम समस्याएं पैदा कीं। अंत में, भले ही हम इसके आसपास काम कर सकते थे, सभी सैंडबॉक्स निर्माण और शेड्यूलिंग के क्रिटिकल पथ पर एक अनशार्डेड Postgres इंस्टेंस को छोड़ना एक बुरा विचार साबित हुआ था।
असीमित स्केल को अनलॉक करना
हमें जल्दी ही एहसास हुआ कि हम जो स्केल चाहते थे उसे प्राप्त करने के लिए हमारी आर्किटेक्चर को नए सिरे से सोचने की आवश्यकता थी। हम लाखों सैंडबॉक्स चलाना और प्रति सेकंड दसियों हज़ार सैंडबॉक्स बनाना चाहते हैं, जिसके लिए मौजूदा किसी भी चीज़ की तुलना में बहुत बेहतर स्केलिंग गुणों की आवश्यकता होती है। जो हमारे पास था उसे विकसित करने की कोशिश करने के बजाय, हमने माना कि सबसे तेज़ और सबसे साफ रास्ता नए सिरे से शुरू करना था।
स्केल के लिए ऑप्टिमाइज़ करने के लिए, हमने तय किया कि O(सैंडबॉक्स) या O(नोड्स) लोड लेने वाली हर चीज़ डिफ़ॉल्ट रूप से क्षैतिज रूप से स्केलेबल होनी चाहिए, सैंडबॉक्स निर्माण पथ जितना संभव हो उतना सरल होना चाहिए, और बाकी सब कुछ गौण होना चाहिए। हम जिस समाधान पर पहुंचे, वह मौजूदा सिस्टम से काफी अलग है। हमने किसी भी प्रकार के केंद्रीय समन्वय को पूरी तरह से समाप्त कर दिया, और सैंडबॉक्स चलाने और बनाने के क्रिटिकल पथ पर हर जगह स्केलेबिलिटी और प्रदर्शन के लिए वैश्विक संगति का व्यापार किया। यहां बताया गया है कि यह कैसे काम करता है:
- एकल, सीरियलाइज़्ड शेड्यूलर के बजाय, हम शेड्यूलिंग सर्वरों का एक बेड़ा चलाते हैं जो सैंडबॉक्स निर्माण अनुरोधों को एक साथ संभालते हैं। एक निर्माण अनुरोध को संभालने के लिए, एक शेड्यूलिंग सर्वर इन-मेमोरी कैश्ड डेटा के खिलाफ एक तेज़ शेड्यूलिंग एल्गोरिथ्म चलाता है। परिणाम यह है कि शेड्यूलिंग क्षैतिज रूप से स्केल करती है, और पारंपरिक कंटेनर शेड्यूलिंग की तुलना में लोड बैलेंसिंग की तरह दिखती है।
- सैंडबॉक्स और वर्कर स्थिति के लिए सत्य का स्रोत के रूप में कार्य करने वाले केंद्रीय, ड्यूरेबल डेटास्टोर के बजाय, जो कि अधिकांश कंटेनर प्लेटफॉर्म कैसे काम करते हैं, हमारे नए सिस्टम में प्रत्येक वर्कर अपना सत्य का स्रोत है। वर्कर समय-समय पर अपनी स्थिति को Redis स्ट्रीम में प्रकाशित करते हैं। शेड्यूलिंग सर्वर इस स्थिति को एसिंक्रोनस रूप से उपभोग करते हैं और शेड्यूलिंग निर्णय लेने के लिए इसका उपयोग करते हैं। एक बार जब कोई शेड्यूलिंग सर्वर यह तय कर लेता है कि किस वर्कर पर सैंडबॉक्स बनाना है, तो वह सैंडबॉक्स बनाने का अनुरोध करने के लिए सीधे RPC के माध्यम से वर्कर से संपर्क करता है। यदि वर्कर के पास मुफ्त संसाधन हैं, तो वे शेड्यूलिंग अनुरोध स्वीकार करते हैं, अन्यथा इसे अस्वीकार कर देते हैं।
- हमारे पास सैंडबॉक्स निर्माण के क्रिटिकल पथ में कोई डेटा स्टोर नहीं है, जो स्केलेबिलिटी और विश्वसनीयता में सुधार करता है। जबकि हमें सैंडबॉक्स मेटाडेटा और परिणामों को ड्यूरेबल स्टोरेज में लिखने की आवश्यकता है, हम ऐसा बड़े पैमाने पर एसिंक्रोनस रूप से करते हैं।
- सैंडबॉक्स निर्माण के अलावा, हमारे पास कोई RPCs नहीं है जो O(सैंडबॉक्स) हैं। वर्कर एकल RPCs में कई सैंडबॉक्स के लिए कंट्रोल संदेशों को बैच करते हैं, डेटा-ओरिएंटेड डिज़ाइन के विचारों की भावना में।

हमारा अंतिम डिज़ाइन, पहली बार जब हमने इसे व्हाइटबोर्ड किया था।

Modal की v2 सैंडबॉक्स आर्किटेक्चर में सैंडबॉक्स निर्माण पथ। सैंडबॉक्स निर्माण अनुरोधों को क्षैतिज रूप से स्केल किए गए शेड्यूलिंग सर्वरों द्वारा संभाला जाता है, जो फिर तेज़ इन-मेमोरी लोड-बैलेंसिंग एल्गोरिथ्म के साथ एक वर्कर का चयन करते हैं, और सैंडबॉक्स बनाने के लिए सीधे वर्कर (कंप्यूट नोड) से संपर्क करते हैं। सैंडबॉक्स ऑब्जेक्ट Redis में संग्रहीत होते हैं, लेकिन क्रिटिकल पथ में नहीं।
परिणाम यह है कि सैंडबॉक्स निर्माण पथ के लिए केवल दो नेटवर्क हॉप्स और एक सस्ते CPU ऑपरेशन की आवश्यकता होती है। कोई केंद्रीय बाधाएं या समन्वय लागत नहीं हैं, विफलता के कोई एकल बिंदु नहीं हैं, और परिणामस्वरूप समग्र सैंडबॉक्स स्केल या सैंडबॉक्स निर्माण थ्रूपुट की कोई व्यावहारिक सीमा नहीं है। हम आवश्यकतानुसार अधिक शेड्यूलर या वर्कर जोड़ सकते हैं। सबसे निकटतम बाधा यह है कि सभी वर्कर एक एकल Redis स्ट्रीम में स्थिति प्रकाशित करते हैं, लेकिन लोड टेस्टिंग ने सुझाव दिया है कि यह 100,000 से अधिक वर्कर तक व्यवहार्य रहता है; और हम वैसे भी स्ट्रीम पर ऑर्डरिंग पर निर्भर नहीं हैं, इसलिए और अधिक स्ट्रीम जोड़ना आसान होगा। डिज़ाइन द्वारा, हम उन मुद्दों से बचते हैं जो मौजूदा समाधानों को स्केल करने से रोकते हैं।
इस समाधान का निर्माण करना आसान नहीं था! पूरी विकास प्रक्रिया में महीनों का काम लगा है, जो हमारे बैकएंड के अधिकांश प्रमुख सिस्टमों में फैला हुआ है। हमने व्हाइटबोर्ड पर घंटों बिताए। हममें से चार लोग एक नए सिस्टम का प्रोटोटाइप बनाने के लिए, बिना किसी विकर्षण के, मियामी बीच में एक किराए के घर में चले गए। हमने आठ दिन तब तक कोड लिखा जब तक हम शारीरिक रूप से नहीं लिख सके, ठीक होने के लिए स्पीड शतरंज खेलते, समुद्र में कूदते, और फिर सीधे कोड पर वापस जाते, अपने नए सिस्टम को साफ और कार्यात्मक बनाने के लिए संघर्ष करते रहे।

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

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

हमारे 1M सैंडबॉक्स परीक्षण से 10k सैंडबॉक्स स्टार्ट टाइम्स का स्कैटरप्लॉट, 1M सैंडबॉक्स में से बेतरतीब ढंग से चुना गया।
हमारे नए सिस्टम पर सैंडबॉक्स स्टार्ट टाइम्स (जब क्लाइंट पहली बार सैंडबॉक्स बनाने का प्रयास करता है, से लेकर जब सैंडबॉक्स उपयोगकर्ता कोड चला सकता है, तक की विलंबता) मीडियन पर आधे सेकंड से भी कम है, और स्केल पर ठोस बनी रहती है। वे हमारे पुराने सिस्टम से भी काफी तेज़ हैं, मुख्यतः क्योंकि शेड्यूलिंग बहुत तेज़ है - अब इसमें केवल दसियों मिलीसेकंड लगते हैं। विलंबता की लंबी पूंछ हमारी इच्छा से कुछ अधिक लंबी है। हम इस पूंछ का अधिकांश हिस्सा कर्नेल और नेटवर्क विवाद (पहले उल्लेखित rtnl लॉक विवाद सहित) को मानते हैं जब कई सैंडबॉक्स एक ही वर्कर पर एक साथ शुरू होते हैं, और हम इसे कम करने के लिए काम कर रहे हैं। साथ ही, स्केल पर पूंछ वास्तविक है। हम उम्मीद करते हैं कि कंटेनर स्टार्टअप पथ को ऑप्टिमाइज़ करने पर इसमें सुधार होगा।
कुल मिलाकर, हम इन प्रदर्शन संख्याओं से बहुत खुश हैं। जैसे-जैसे एजेंट दुनिया पर कब्जा कर लेंगे, स्पष्ट रूप से हम उनके साथ स्केल कर सकते हैं।
खुद देखें
जल्द ही यह नया सिस्टम Modal पर सभी सैंडबॉक्स शेड्यूलिंग को बैक करेगा, लेकिन यह पहले से ही बीटा में उपलब्ध है। आप अपने कोड में एक सरल बदलाव के साथ ऑप्ट इन करना चाहते हैं। यदि आपको बहुत सारे सैंडबॉक्स चलाने की आवश्यकता है, तो इसे आज़माएं, और हमसे बात करें!
आभार
इस परियोजना में बहुत से लोगों ने खून, पसीना और आंसू बहाए हैं। हमारा Miami POC कॉलिन वेल्ड (मैं), डेनियल शार, वाल्टर टैंग और ग्लेब पोसोबिन द्वारा बनाया गया था, और फिर वाल्टर, कॉलिन, कॉनर एडम्स, अक्षय बलवाली, टॉम वाइल्डेनहेन, स्कॉट हाओ और टेलर बाल्डविन द्वारा प्रोडक्शन में लाया गया।





