javascript - ما هي أفضل طريقة يمكنني بها توسيع نطاق تطبيق nodejs؟




node.js sockets (2)

أساسيات

في الوقت الحالي ، أحاول بعض أصدقائي تطوير لعبة متصفح مصنوعة في nodejs. إنها لعبة مطلق النار من أعلى إلى أسفل ومتعددة اللاعبين ، ومعظم كود العميل وجانب الخادم في javascript. لدينا اتجاه عام جيد نود أن نصل إليه ، ونحن نمتلك الكثير من المتعة في تطوير اللعبة. أحد أهدافنا عند صنع هذه اللعبة هو جعل الأمر صعبا قدر الإمكان للغش. تفعل ذلك ، لدينا كل منطق لعبة التعامل مع جانب الخادم. يرسل العميل مدخلاته للخادم فقط عبر مقبس الويب ، ويقوم الخادم بتحديث العميل (أيضًا مقبس الويب) مع ما يحدث في اللعبة. ها هي بداية مشكلتنا.

كل الرياضيات الجانبية للملقم تزداد إلى حد كبير ، ونجد أننا بحاجة إلى التوسع في طريقة للتعامل مع أي شيء أكثر من 10 لاعبين (نريد أن نكون قادرين على استضافة الكثير). في البداية كنا قد توصلنا إلى أننا يمكن أن نرتفع عموديا كما كنا نحتاج إليه ، ولكن بما أن nodejs واحدة مترابطة ، فلا يمكن إلا أن تستفيد من قلب واحد. هذا يعني أن الحصول على خادم أكبر لن يساعدك في هذه المشكلة. حلنا الوحيد هو قياس أفقيا.

لماذا نسأل هنا

لم نتمكن من العثور على أي أمثلة جيدة حول كيفية توسيع نطاق لعبة nodejs. لدينا حالة استخدام خاصة جدا ، وعلى الرغم من أننا بذلنا قصارى جهدنا للقيام بذلك من قبل أنفسنا ، يمكن أن نستفيد حقا من الآراء والمشورة الخارجية

تفاصيل

لقد وضعنا الكثير من التفكير في كيفية حل هذه المشكلة. كنا نعمل عليه لأكثر من أسبوع. هذا ما قمنا بتجميعه حتى الآن:

أربعة أنواع من الخوادم

نحن نقوم بتقسيم المهام إلى 4 "أنواع" مختلفة من الخوادم. كل واحد سيكون لديه مهمة محددة يكملها.

الخادم الوكيل

وسيجلس الخادم الوكيل في مقدمة المكدس بالكامل ، ويكون الخادم الوحيد الذي يمكن الوصول إليه مباشرة من الإنترنت (قد يكون هناك المزيد من هذه الخوادم). من شأنه أن يكون haproxy على ذلك ، وأنه من شأنه توجيه جميع الاتصالات إلى خوادم الويب. لقد اخترنا haproxy بسبب مجموعة الميزات الغنية والموثوقية وسرعة لا تقهر.

خادم الويب

سيتلقى خادم الويب طلبات الويب ويقدم جميع صفحات الويب. كما يمكنهم التعامل مع إنشاء / إدارة اللوبي وإنشاء / إدارة اللعبة. للقيام بذلك ، سيخبرون خوادم اللعبة بما لديها من ردهات ، وما هو المستخدمون في ذلك اللوبي ، ومعلومات حول اللعبة التي سيلعبونها. ثم تقوم خوادم الويب بتحديث خوادم اللعبة حول إدخال المستخدم ، وسيقوم خادم اللعبة بتحديث خوادم الويب (التي ستقوم بتحديث العملاء) بما يحدث في اللعبة. ستستخدم خوادم الويب مآخذ توصيل TCP للتواصل مع خوادم الألعاب حول أي نوع من أنواع الإدارة ، وستستخدم مآخذ UDP عند الاتصال حول تحديثات الألعاب. هذا من شأنه أن يتم كل ذلك مع nodejs.

خادم اللعبة

سيعالج خادم اللعبة كل لعبة الرياضيات والتحديثات المتغيرة حول اللعبة. خوادم اللعبة أيضا التواصل مع خوادم ديسيبل لتسجيل احصائيات باردة حول اللاعبين في اللعبة. سيتم ذلك مع nodejs.

خادم ديسيبل

يستضيف الملقم db قاعدة البيانات. هذا الجزء تبين أنه الأسهل منذ أن وجدنا rethinkdb ، أروع ديسيبل من أي وقت مضى. هذا المقياس بسهولة ، وبشكل غريب بشكل كافي ، تبين أنه أسهل جزء في توسيع نطاق تطبيقنا.

بعض التفاصيل الأخرى

إذا كنت تواجه مشكلة في الحصول على رأسك من خلال مجموعتنا الكاملة ، فابحث عن هذا ، إنه مخطط شبه دقيق عن الكيفية التي نعتقد أننا سنقوم بتوسيع نطاقها.

إذا كنت مجرد فضول ، أو تعتقد أنه قد يكون من المفيد النظر إلى لعبتنا ، فإنه يتم استضافته حاليًا في حالة عدم القياس هنا.

بعض الأشياء التي لا نريدها

  • لا نريد استخدام وحدة نظام المجموعات من العقيدات. إنه غير مستقر ( here ) ، ولا يتدرج إلى خوادم أخرى ، فقط معالجات أخرى. نود أن نأخذ قفزة إلى التحجيم الأفقي.

سؤالنا ، لخص

نأمل أن نسير في الاتجاه الصحيح ، وأنجزنا واجباتنا المدرسية ، لكننا لسنا متأكدين. يمكننا بالتأكيد أخذ بعض النصائح حول كيفية القيام بذلك بالطريقة الصحيحة.

شكر

أدرك أن هذا سؤال طويل جدًا ، وأن إجابة مدروسة لن تكون سهلة ، لكني سأقدر ذلك حقًا.

شكر!!


بعد أفكاري العفوية في قضيتك:

استخدام متعدد النواة

يمكن أن يتسع نطاق node.js مع العديد من النوى أيضًا. كيف يمكنك أن تقرأ على سبيل المثال هنا ( أو تفكر في ذلك فقط: لديك خيط / عملية واحدة تعمل على نواة واحدة ، ما الذي تحتاج إليه لاستخدام نوى متعددة؟ مؤشرات ترابط متعددة أو عمليات متعددة. دفع العمل من الخيط الرئيسي إلى خيوط أخرى أو العمليات وانت القيام به ).

أنا شخصياً أقول إنه من الصبياني تطوير تطبيق ، لا يستفيد من نوى متعددة. إذا كنت تستخدم بعض العمليات في الخلفية ، حسنًا ، ولكن إذا كنت تعمل حتى الآن فقط في حلقة الحدث الرئيسية node.js ، فيجب عليك بالتأكيد استثمار بعض الوقت لجعل التطبيق قابلاً للتحجيم على النوى.

تنفيذ شيء مثل IPC ليست بهذه السهولة من جانب الطريق. يمكنك القيام بذلك ، ولكن إذا كانت حالتك معقدة ، فربما أنت مستعد للذهاب مع وحدة المجموعة. من الواضح أن هذا ليس المفضل لديك ، ولكن فقط لأن هناك شيء يسمى "تجريبي" ، هذا لا يعني أنه تافه. مجرد محاولة إعطائها ، وربما يمكنك حتى إصلاح بعض الخلل من الوحدة النمطية على الطريق. من الأفضل استخدام بعض البرامج المستخدمة على نطاق واسع للمشاكل المعقدة ، بدلاً من ابتكار عجلة جديدة.

يجب عليك أيضًا (إذا لم تكن بالفعل) التفكير في استخدام (حكيم) لوظائف nextTick . هذا يسمح لحلقة الحدث الرئيسية بإيقاف بعض المهام المكثفة للـ CPU والقيام بأعمال أخرى في هذه الأثناء. يمكنك أن تقرأ عنه على سبيل المثال هنا .

أفكار عامة حول الحسابات

يجب عليك بالتأكيد إلقاء نظرة فاحصة على الخوارزميات الخاصة بمحرك اللعبة. لقد لاحظت بالفعل أن هذا هو عنق الزجاجة في الوقت الحالي وأن الحسابات هي الجزء الأكثر أهمية في الغالب في كل لعبة. يحل القياس هذه المشكلة بطريقة واحدة ، ولكن التدرج يقدم مشكلات أخرى. كما لا يمكنك رمي "التحجيم" كحل للمشكلة على كل شيء ونتوقع أن تختفي كل مشكلة.

أفضل رهان هو جعل رمز اللعبة الخاص بك أنيق وسريع. فكر في كيفية حل المشكلات بكفاءة. إذا لم تتمكن من حل شيء ما في Javascript بكفاءة ، ولكن يمكن بسهولة استخراج المشكلة ، فلماذا لا تكتب مكونًا C صغيرًا بدلاً من ذلك؟ هذا يعد أيضًا عملية منفصلة ، مما يقلل من الحمل على حلقة الحدث node.js الرئيسية.

الوكيل؟

شخصيا أنا لا أرى ميزة مستوى الوكيل في الوقت الحالي. يبدو أنك لا تتوقع عددًا كبيرًا من المستخدمين ، ولذلك لن تحتاج إلى حل المشكلات مثل CDN أو أي شيء ... لا بأس في التفكير في الأمر ، لكنني لن أستثمر الكثير من الوقت هناك الآن.

من الناحية الفنية ، هناك فرصة كبيرة أن يوفر برنامج خادم الويب لديك وظيفة الخادم الوكيل على أي حال. لذلك لا بأس أن يكون ذلك على الورق ، لكنني لن أخطط مع الأجهزة المخصصة في الوقت الحالي.

الخاتمه

الباقي يبدو أكثر أو أقل غرامة بالنسبة لي.


متأخرة قليلاً من اللعبة ، ولكن انظر هنا: http://goldfirestudios.com/blog/136/Horizontally-Scaling-Node.js-and-WebSockets-with-Redis

لم تذكر أي شيء يتعلق بإدارة الذاكرة. كما تعلم ، لا تشارك nodejs ذاكرتها بعمليات أخرى ، لذا فإن قاعدة البيانات في الذاكرة أمر لا بد منه إذا كنت ترغب في القياس. ( Memcache ، Memcache ، إلخ). تحتاج إلى إعداد حدث ناشر و مشترك على كل عقدة لقبول الطلبات الواردة من redis . وبهذه الطريقة ، يمكنك زيادة عدد خوادم nilo من الخوادم (أمام HAProxy) واستخدام البيانات المنقولة بالأنابيب من redis .

يوجد أيضًا هذا الملحق node : http://blog.varunajayasiri.com/shared-memory-with-nodejs الذي يتيح لك مشاركة الذاكرة بين العمليات ، ولكن يعمل فقط في Linux. سيساعدك هذا إذا كنت لا ترغب في إرسال البيانات عبر العمليات المحلية طوال الوقت أو تضطر إلى التعامل مع nodes ipc api.

يمكنك أيضا تشعب عمليات الطفل داخل node لعزل v8 جديد للمساعدة في المهام المعيارية باهظة الثمن. على سبيل المثال ، يمكن للاعبين قتل الوحوش والحصول على الكثير من المسروقات داخل لعبة آر بي جي العمل. لدي عملية طفل تدعى LootGenerater ، وبشكل أساسي كلما قام لاعب بقتل وحش يرسل id اللعبة و mob_id و user_id إلى العملية عبر واجهة IPC الافتراضية. وبمجرد redis عملية الطفل له ، فإنه يتكرر على طاولة redis الكبيرة ويدير العناصر (المخازن إلى redis ، أو أيا كان) redis إلى الوراء.

هذا يساعد في تحرير حلقة الحدث بشكل كبير ، وفكرة واحدة فقط يمكنني التفكير فيها لمساعدتك على التوسع. ولكن الأهم من ذلك أنك ستحتاج إلى استخدام نظام قاعدة بيانات في الذاكرة وتأكد من تصميم بنية رمز اللعبة الخاصة بك حول أي نظام قاعدة بيانات تستخدمه. لا تجعل الخطأ الذي ارتكبته الآن بحاجة إلى إعادة كتابة كل شيء :)

أتمنى أن يساعدك هذا!

ملاحظة: إذا قررت الذهاب مع Memcache ، فستحتاج إلى استخدام نظام pub / sub آخر.





autoscaling