javascript - मेरे नोडजेस ऐप को स्केल करने का सबसे अच्छा तरीका क्या है?




node.js sockets (2)

मूल बातें

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

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

हम यहाँ क्यों पूछ रहे हैं

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

विवरण

हमने इस समस्या को हल करने के तरीके में पहले से ही बहुत कुछ सोचा है। हम एक सप्ताह से अधिक समय तक इस पर काम कर रहे हैं। यहां हमने जो कुछ भी रखा है, वह यहां है:

चार प्रकार के सर्वर

हम कार्यों को 4 अलग-अलग प्रकार के सर्वरों में विभाजित कर रहे हैं। प्रत्येक के पास एक विशिष्ट कार्य होगा जो इसे पूरा करता है।

प्रॉक्सी सर्वर

प्रॉक्सी सर्वर पूरे ढेर के सामने बैठेगा, और इंटरनेट से सीधे पहुंचने वाला एकमात्र सर्वर होगा (संभावित रूप से इनमें से अधिक हो सकता है)। यह उस पर haproxy होगा, और यह सभी सर्वरों को वेब सर्वर पर रूट करेगा। हमने अपने समृद्ध फीचर सेट, विश्वसनीयता और लगभग नामुमकिन गति के कारण हैपरोक्सी चुना है।

वेब सर्वर

वेब सर्वर वेब-अनुरोध प्राप्त करेगा, और सभी वेब पेजों की सेवा करेगा। वे लॉबी निर्माण / प्रबंधन और गेम निर्माण / प्रबंधन को भी संभालेंगे। ऐसा करने के लिए, वे गेम सर्वर को बताएंगे कि इसमें क्या लॉबी है, उपयोगकर्ता उस लॉबी में क्या हैं, और वे गेम के बारे में जानकारी जो वे खेलेंगे। वेब सर्वर तब उपयोगकर्ता इनपुट के बारे में गेम सर्वर अपडेट करेंगे, और गेम सर्वर गेम में क्या हो रहा है, इसके बारे में वेब सर्वर अपडेट करेगा (जो ग्राहकों को अपडेट करेगा)। वेब सर्वर किसी भी प्रकार के प्रबंधन के बारे में गेम सर्वर के साथ संवाद करने के लिए टीसीपी सॉकेट का उपयोग करेंगे, और गेम अपडेट के बारे में संवाद करते समय वे यूडीपी सॉकेट का उपयोग करेंगे। यह सब नोडज के साथ किया जाएगा।

खेल सर्वर

गेम सर्वर गेम के बारे में सभी गेम गणित और परिवर्तनीय अपडेट को संभालेगा। गेम सर्वर गेम में खिलाड़ियों के बारे में अच्छे आंकड़े रिकॉर्ड करने के लिए डीबी सर्वर के साथ संवाद भी करता है। यह नोडज के साथ किया जाएगा।

डीबी सर्वर

डीबी सर्वर डेटाबेस होस्ट करेगा। यह हिस्सा वास्तव में सबसे आसान साबित हुआ क्योंकि हमने कभी भी सबसे अच्छा डीबी rethinkdb पाया। यह स्केल आसानी से, और विचित्र रूप से पर्याप्त है, हमारे आवेदन को स्केल करने का सबसे आसान हिस्सा साबित हुआ।

कुछ अन्य विवरण

यदि आपको हमारे पूरे गेटअप के आसपास अपना सिर प्राप्त करने में परेशानी हो रही है, तो इसे देखें, यह एक अर्द्ध सटीक चार्ट है कि हम कैसे सोचते हैं कि हम स्केल करेंगे।

यदि आप केवल उत्सुक हैं, या सोचें कि यह हमारे खेल को देखने में सहायक हो सकता है, तो वर्तमान में यह यहां अपने गैर-स्केल्ड राज्य में होस्ट किया गया है।

कुछ चीजें जिन्हें हम नहीं चाहते हैं

  • हम नोडज के क्लस्टर मॉड्यूल का उपयोग नहीं करना चाहते हैं। यह स्थिर नहीं है ( here कहा गया here ), और यह अन्य सर्वरों, केवल अन्य प्रोसेसर के लिए स्केल नहीं करता है। हम केवल क्षैतिज स्केलिंग के लिए छलांग लेना चाहते हैं।

हमारा सवाल, संक्षेप में

हमें आशा है कि हम सही दिशा में जा रहे हैं, और हमने अपना होमवर्क किया है, लेकिन हम निश्चित नहीं हैं। हम निश्चित रूप से इसे सही तरीके से कैसे करें इस पर कुछ सुझाव ले सकते हैं।

धन्यवाद

मुझे एहसास है कि यह एक बहुत लंबा सवाल है, और एक अच्छी तरह से सोचा जवाब बनाना आसान नहीं होगा, लेकिन मैं वास्तव में इसकी सराहना करता हूं।

धन्यवाद!!


आपके मामले पर अपने सहज विचारों के बाद:

मल्टीकोर उपयोग

node.js कई कोर के साथ भी स्केल कर सकते हैं। कैसे, आप यहां उदाहरण के लिए पढ़ सकते हैं ( या बस इसके बारे में सोचें: आपके पास एक कोर पर चलने वाला एक थ्रेड / प्रक्रिया है, आपको एकाधिक कोर का उपयोग करने की क्या ज़रूरत है? एकाधिक धागे या एकाधिक प्रक्रियाएं। मुख्य धागे से अन्य थ्रेड तक काम पुश करें या प्रक्रियाओं और आप कर रहे हैं )।

मैं व्यक्तिगत रूप से कहूंगा कि यह एक एप्लीकेशन विकसित करने के लिए बचपन है, जो कई कोरों का उपयोग नहीं करता है। यदि आप कुछ पृष्ठभूमि प्रक्रियाओं का उपयोग करते हैं, तो ठीक है, लेकिन यदि आप अभी तक केवल node.js मुख्य ईवेंट लूप में काम करते हैं, तो आपको निश्चित रूप से कोर पर स्केलेबल बनाने के लिए कुछ समय निवेश करना चाहिए।

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

आपको nextTick कार्यक्षमता के (बुद्धिमान) उपयोग के बारे में भी सोचना चाहिए (यदि आप पहले से नहीं हैं)। यह मुख्य घटना लूप को कुछ सीपीयू गहन कार्य को रोकने और इस बीच अन्य कार्य करने की अनुमति देता है। उदाहरण के लिए आप इसके बारे में पढ़ सकते हैं।

गणना पर सामान्य विचार

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

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

प्रॉक्सी?

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

तकनीकी रूप से आपके वेबसर्वर सॉफ़्टवेयर को प्रॉक्सी कार्यक्षमता प्रदान करने का एक उच्च मौका है। तो कागज पर रखना ठीक है, लेकिन मैं अभी समर्पित हार्डवेयर के साथ योजना नहीं बनाऊंगा।

उपसंहार

बाकी मुझे कम या ज्यादा ठीक लगता है।


खेल के लिए बहुत देर हो चुकी है, लेकिन यहां एक नज़र डालें: http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis

आपने स्मृति प्रबंधन के साथ कुछ भी करने का जिक्र नहीं किया है। जैसा कि आप जानते हैं, nodejs अन्य मेमोरी के साथ अपनी मेमोरी साझा नहीं करता है, इसलिए यदि आप स्केल करना चाहते हैं तो इन-मेमोरी डेटाबेस एक जरूरी है। ( Redis , Memcache , आदि)। redis से आने वाले अनुरोधों को स्वीकार करने के लिए आपको प्रत्येक नोड पर एक प्रकाशक और ग्राहक ईवेंट सेट अप करने की आवश्यकता है। इस तरह, आप x nilo सर्वरों (आपके HAProxy के सामने) को स्केल कर सकते हैं और redis से पाइप किए गए डेटा का उपयोग कर सकते हैं।

यह node एडन भी है: http://blog.varunajayasiri.com/shared-memory-with-nodejs जो आपको प्रक्रियाओं के बीच स्मृति साझा करने देता है, लेकिन केवल लिनक्स के अंतर्गत काम करता है। इससे मदद मिलेगी यदि आप हर समय स्थानीय प्रक्रियाओं में डेटा नहीं भेजना चाहते हैं या nodes आईपीसी एपीआई से निपटना चाहते हैं।

महंगे सीपीयू बाध्य कार्यों में मदद के लिए आप एक नए v8 अलग करने के लिए node के भीतर बाल प्रक्रियाओं को भी फोर्क कर सकते हैं। उदाहरण के लिए, खिलाड़ी राक्षसों को मार सकते हैं और मेरे एक्शन आरपीजी गेम के भीतर लूट प्राप्त कर सकते हैं। मेरे पास LootGenerater नामक एक बाल प्रक्रिया है, और मूल रूप से जब भी कोई खिलाड़ी राक्षस को मारता है तो यह डिफ़ॉल्ट आईपीसी एपीआई के माध्यम से प्रक्रिया में गेम id , mob_id , और user_id .send । एक बार जब बच्चे की प्रक्रिया इसे प्राप्त हो जाती है, तो यह बड़ी लूट तालिका पर फिर से शुरू होती है और वस्तुओं ( redis , या जो कुछ भी स्टोर करती है) का प्रबंधन करती है और इसे वापस पाइप करती है।

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

उम्मीद है की यह मदद करेगा!

नोट: यदि आप मेमकैच के साथ जाने का निर्णय लेते हैं, तो आपको एक और पब / सब सिस्टम का उपयोग करने की आवश्यकता होगी।





autoscaling