क्या यह हमारे MMORPG मोबाइल गेम के लिए सही आर्किटेक्चर है?


14

इन दिनों मैं अपनी कंपनी के लिए एक नए MMORPG मोबाइल गेम की वास्तुकला डिजाइन करने की कोशिश कर रहा हूं। यह खेल माफिया युद्धों, iMobsters, या जोखिम के समान है। मूल विचार अपने विरोधियों (ऑनलाइन उपयोगकर्ताओं) से लड़ने के लिए एक सेना तैयार करना है।

हालाँकि मैंने पहले कई मोबाइल ऐप पर काम किया है लेकिन यह मेरे लिए कुछ नया है। बहुत संघर्ष के बाद, मैं एक वास्तुकला के साथ आया हूं, जिसे उच्च-स्तरीय प्रवाह आरेख की मदद से चित्रित किया गया है:

उच्च-स्तरीय प्रवाह आरेख

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

इस मॉडल के साथ, मुझे यकीन नहीं है कि निम्नलिखित मुद्दों से कैसे निपटा जाए:

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

मुझे यकीन नहीं है कि यह एक कुशल समाधान है और यह कैसे पैमाना होगा। मैं वास्तव में सराहना करूंगा यदि ऐसे लोग जो पहले से ही ऐसे ऐप्स पर काम कर चुके हैं, अपने अनुभव साझा कर सकते हैं जो मुझे कुछ बेहतर करने में मदद कर सकते हैं। अग्रिम में धन्यवाद।

अतिरिक्त जानकारी:

क्लाइंट-साइड को C ++ गेम इंजन में लागू किया जाता है जिसे मुरब्बा कहा जाता है। यह एक क्रॉस प्लेटफॉर्म गेम इंजन है जिसका मतलब है कि आप अपने ऐप को सभी प्रमुख मोबाइल ओएस पर चला सकते हैं। हम निश्चित रूप से थ्रेडिंग को प्राप्त कर सकते हैं और जिसे मेरे प्रवाह आरेख में भी चित्रित किया गया है। मैं क्लाइंट के लिए सर्वर और SQLite के लिए MySQL का उपयोग करने की योजना बना रहा हूं।

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

डेटाबेस सिंक्रनाइज़ेशन के लिए मेरे पास दो समाधान हैं:

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

2
मैं MsSQL का मूल्यांकन लेगा और इसके साथ फिडेल करूँगा - मुझे यकीन नहीं है कि MySQL प्रतिकृति के संदर्भ में क्या प्रदान करता है लेकिन MsSQL 2008 R2 आपको चुनने के लिए प्रतिकृति (5-6) तकनीकों का एक LOAD देता है। बस एक विचार, MySQL या किसी भी चीज़ से नफरत नहीं है, लेकिन Microsoft वास्तव में क्लस्टरिंग में अच्छा है।
जोनाथन डिकिंसन

1
@ जोनाथन डिकिंसन: MySQL क्लस्टर है: P
कोयोट

1
PostgreSQL को भी देखें - संस्करण 9 में प्रतिकृति तकनीक है, PostgreSQL में भारी भार से निपटने के लिए एक उत्कृष्ट लंबे समय से चली आ रही प्रतिष्ठा है, डेवलपर्स के कई अनुकूलन नट्स लगते हैं, और सबसे अच्छा यह खुला स्रोत है और सभी उपयोगों के लिए पूरी तरह से मुक्त है। (वाणिज्यिक सहित)।
Randolf Richardson

बात यह है कि हम क्लाइंट और सर्वर साइड पर एक ही डेटाबेस का उपयोग नहीं कर सकते हैं। मुझे लगता है कि क्लाइंट के लिए सबसे उपयुक्त DB SQLite होगा ताकि यह बहुत सारे संसाधनों का उपभोग न करे क्योंकि ऐप मोबाइल उपकरणों पर चल रहा होगा। जबकि सर्वर भाग पर काम करने वाला व्यक्ति केवल MySQL जानता है, इसलिए हमने इसे चुना है। इसके अलावा मैंने सुना है कि अधिकांश MMO खेल MySQL डेटाबेस का उपयोग करते हैं।
umair

1
@umair: क्लाइंट साइड SQLite हो सकता है (उदाहरण के लिए iPhone पर यह पहले से उपलब्ध है)। लेकिन आप बस एक फ़ाइल (जो SQLite वैसे भी करता है) में आवश्यक प्रासंगिक डेटा को स्टोर करने के लिए चुना जा सकता है और ग्राहक पक्ष DB के साथ परेशान नहीं कर सकते हैं जैसे आप जावास्क्रिप्ट ऐप के साथ करते हैं।
कोयोट

जवाबों:


15

यदि यह "वास्तविक समय" खेल नहीं है, तो इस मायने में कि खिलाड़ियों को खेल के दृश्य पर किसी अन्य खिलाड़ी के कार्यों का तत्काल परिणाम देखने की आवश्यकता नहीं है, तो आपको HTTP अनुरोधों के साथ ठीक होना चाहिए। लेकिन HTTP के ओवरहेड को ध्यान में रखें।

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

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

कुछ गेम स्थानीय DB का उपयोग भी नहीं करते हैं, वे बस जरूरत पड़ने पर सर्वर से संबंधित जानकारी को पूल करके स्थिति का ट्रैक रखते हैं।

यदि स्थानीय घटनाओं को खोना स्वीकार्य नहीं है, तो हां, आपके पास स्थानीय भंडारण होना चाहिए और उस भंडारण को जितनी बार संभव हो उतना बचाना चाहिए। आप प्रत्येक नेटवर्क भेजने से पहले ऐसा करने का प्रयास कर सकते हैं।

सक्रिय उपयोगकर्ताओं की जाँच करने के लिए, हम हर 20 सेकंड में HTTP के साथ एक सफल गेम पर पिंग करते थे ... यह मान तुरंत चला गया क्योंकि सर्वर ओवरलोड हो गए हैं :( सर्वर टीम ने सफलता के बारे में नहीं सोचा था। इसलिए मैं आपको जोड़ने के लिए कहूंगा। आपके संचार प्रोटोकॉल में एक संदेश या कुछ विशेष प्रकार के शीर्षलेख जो आपको अपने ग्राहकों को पुन: कॉन्फ़िगर करने देंगे (आवृत्ति लोड संतुलन और अन्य संचार संबंधी मूल्यों के लिए)।

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

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

HTTP का उपयोग करना एक बुरा विचार नहीं है, क्योंकि बाद में, यह आपको Flash या HTML5 क्लाइंट के साथ बहुत आसानी से एकीकृत करने की अनुमति देगा, यह लचीला है, आप किसी भी प्रकार की सर्वर स्क्रिप्टिंग भाषा का उपयोग कर सकते हैं और मूल लोड संतुलन तकनीकों के साथ बाद में बहुत प्रयास किए बिना अधिक सर्वर जोड़ सकते हैं अपने बैकएंड को स्केल करने के लिए।

आपके पास करने के लिए बहुत कुछ है लेकिन यह एक मजेदार काम है ... इसलिए आनंद लें!


3
+1 के लिए 'HTML शायद काफी अच्छा है' क्योंकि यह शायद :) है।
जोनाथन डिकिंसन

1
@ कोयोट: समय निकालने और इस तरह के एक विस्तृत जवाब देने के लिए धन्यवाद। वास्तव में अन्य क्लाइंट को सहायता प्रदान करने के लिए आपका HTTP विचार पसंद है।
umair

1
बल आपके साथ हो सकता है :)
कोयोट

5

सर्वर और क्लाइंट डेटाबेस को सिंक्रनाइज़ करने का सबसे अच्छा तरीका क्या होगा?

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

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

क्या सर्वर को अपडेट करने से पहले किसी घटना को स्थानीय DB में सहेजा जाना चाहिए?

यदि सर्वर ने कभी भी घटना नहीं घटाई तो क्या होगा? क्लाइंट को वैसे भी घटनाओं के बारे में निर्णय नहीं लेना चाहिए, क्योंकि क्लाइंट पर भरोसा नहीं किया जा सकता है।

मैंने देखा कि आप स्थानीय DB के बारे में दो तरीकों से बात कर रहे हैं: एक, "चीजों के लिए जो अक्सर बदलती नहीं हैं" और दो, घटनाओं के लिए। ये वास्तव में एक ही डेटाबेस में नहीं होना चाहिए, ऊपर दिए गए कारणों के लिए - आप डेटाबेस में व्यक्तिगत डेटा पंक्तियों को मर्ज करने या अलग करने की कोशिश नहीं करना चाहते हैं। उदाहरण के लिए, संदर्भात्मक अखंडता एक समस्या बन जाती है जब क्लाइंट के पास किसी आइटम का संदर्भ होता है जिसे आप सर्वर से हटाने का निर्णय लेते हैं। या यदि क्लाइंट एक पंक्ति बदलता है और सर्वर एक पंक्ति बदलता है, तो कौन सा परिवर्तन पूर्ववर्तीता लेता है और क्यों?

क्या सरल HTTP अनुरोध सिंक्रनाइज़ेशन के उद्देश्य को पूरा करेंगे?

हां, बशर्ते वे काफी हद तक निराले या छोटे हों। HTTP बैंडविड्थ-कुशल नहीं है इसलिए इसे ध्यान में रखें।

कैसे पता करें कि वर्तमान में कौन से उपयोगकर्ता लॉग इन हैं? (एक तरीका यह हो सकता है कि ग्राहक सक्रिय रहने के लिए हर एक एक्स-मिनट के बाद सर्वर को एक अनुरोध भेजते रहें। अन्यथा ग्राहक को निष्क्रिय मानें)।

यदि आप HTTP जैसे क्षणिक प्रोटोकॉल का उपयोग करते हैं, तो यह एक उचित विचार है। जब सर्वर को क्लाइंट से संदेश मिलता है, तो आप उस क्लाइंट के लिए 'अंतिम बार देखा गया' समय अपडेट कर सकते हैं।

क्या क्लाइंट साइड सत्यापन पर्याप्त हैं? यदि नहीं, तो सर्वर को कुछ मान्य नहीं करने पर किसी कार्रवाई को कैसे वापस करना है?

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


1
आप इसे किसी न किसी। आप DBs को सिंक करने के बारे में सही हैं। क्लाइंट को कभी भी DB को अपने आप में परिवर्तित नहीं करना चाहिए ... बस कॉल फ़ंक्शन जो सर्वर पर चलते हैं और गेम के लॉगिक्स का उपयोग करके DB को अपडेट करते हैं, फिर परिणाम प्राप्त करते हैं।
कोयोट

@ किलोटन: मेरे मॉडल में बहने के लिए धन्यवाद
umair

@Kylotan: "सबसे आसान तरीका डेटाबेस को एक एकल फ़ाइल के रूप में लागू करना है जिसे आप स्थानांतरित कर सकते हैं। यदि आप डेटाबेस के बीच अंतर की तुलना करने की कोशिश कर रहे हैं तो यह दर्द की दुनिया है, और मैं अनुभव से बोलता हूं।" इसका मतलब यह है कि सभी डेटा डाउनलोड किया जाता है जब हर बार एप्लिकेशन लॉन्च किया जाता है। ऐसी चीजें हैं जो बहुत बार बदलती हैं और इसलिए उन्हें हर बार डाउनलोड करना स्वीकार्य नहीं हो सकता है। इससे ऐप का लॉन्च समय भी काफी बढ़ जाएगा। कोई विचार?
umair

यदि डेटा छोटा है, तो समस्या दूर हो जाती है। मुझे आश्चर्य होगा कि अगर स्थैतिक डेटा का आपका केंद्रीकृत डेटाबेस बहुत बड़ा था। लेकिन वैसे भी, यदि आप स्थैतिक डेटा को छोटे भागों में विभाजित करते हैं, तो आपको केवल उन लोगों को भेजने की आवश्यकता है जो पिछली बार से बदल गए हैं। निश्चित रूप से, यदि आप प्रत्येक पंक्ति में एक संशोधन समय रखने के लिए तैयार हैं, तो आप इसे प्रति-पंक्ति के आधार पर कर सकते हैं। आम तौर पर मैं रिलेशनल डीबी के बाहर स्थिर डेटा रखना पसंद करता हूं, ताकि मुझे इसे आसानी से अधिलेखित करने की अनुमति मिल सके।
काइलोटन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.