تحديث البرامج القديمة: برمجة MUD باستخدام Erlang و CloudI

نشرت: 2022-03-11

ما هو التحديث القديم؟

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

تنتشر الحاجة إلى تحديث التعليمات البرمجية والأنظمة القديمة لتلبية متطلبات الأداء والمعالجة الحالية. يقدم هذا المنشور دراسة حالة عن استخدام لغة برمجة Erlang ، و CloudI Service Oriented Architecture (SOA) المستندة إلى Erlang ، لتكييف الكود القديم - على وجه الخصوص ، مجموعة عمرها عقود من الكود المصدري C - للقرن الحادي والعشرين .

في العديد من المؤسسات الكبيرة ، تستهلك صيانة الأنظمة القديمة أكثر من 90٪ من موارد أنظمة المعلومات.

ذبح تنين كود المصدر

منذ سنوات ، كنت من أشد المعجبين بألعاب الإنترنت متعددة اللاعبين القائمة على النصوص والمعروفة باسم الزنزانات متعددة المستخدمين (MUDs). لكنهم كانوا دائمًا مليئين بمشاكل الأداء. قررت أن أعود إلى كومة من كود مصدر C عمرها عقود وأرى كيف يمكننا تحديث هذا الكود القديم ودفع هذه الألعاب المبكرة عبر الإنترنت إلى حدودها. على مستوى عالٍ ، كان هذا المشروع مثالًا رائعًا لاستخدام Erlang لتكييف البرامج القديمة لتلبية متطلبات القرن الحادي والعشرين.

ملخص موجز:

  • الهدف : خذ لعبة فيديو MUD قديمة محدودة بعدد 50 لاعبًا وادفع شفرة المصدر الخاصة بها لدعم الآلاف والآلاف من الاتصالات المتزامنة.
  • المشكلة : الكود المصدري القديم ذو الخيط المفرد سي.
  • الحل : CloudI ، خدمة قائمة على Erlang توفر التسامح مع الأخطاء وقابلية التوسع.

تحديث البرامج القديمة: برمجة MUD باستخدام Erlang و CloudI

ما هو MUD المستند إلى النص؟

طورت جميع ألعاب تقمص الأدوار متعددة اللاعبين عبر الإنترنت (MMORPGs) - مثل World of Warcraft و EverQuest - ميزات يمكن إرجاع أصولها المبكرة إلى الألعاب النصية متعددة اللاعبين عبر الإنترنت القديمة والمعروفة باسم الزنزانات متعددة المستخدمين (MUDs).

كان MUD الأول هو Essex MUD (أو MUD1) لـ Roy Trubshaw والذي تم تطويره في الأصل في عام 1978 باستخدام لغة المجمع MARO-10 على DEC PDP-10 ، ولكن تم تحويله إلى BCPL ، وهو سلف لغة البرمجة C (وكان يعمل حتى 1987). (كما ترى ، هذه الأشياء أقدم من معظم المبرمجين.)

اكتسبت MUDs شعبية تدريجية خلال أواخر الثمانينيات وأوائل التسعينيات من القرن الماضي مع العديد من قواعد أكواد MUD المكتوبة في C. بناءً على نفس شفرة مصدر DikuMUD. (خلال هذا الإطار الزمني ، بالمناسبة ، أصبحت MUDs تُعرف بدلاً من ذلك باسم "المدمر متعدد الطلاب" نظرًا لعدد الطلاب الجامعيين الذين فشلوا في الدراسة بسبب هوسهم بهم.)

مشكلة الوحل القديم

إن شفرة مصدر C MUD التاريخية (بما في ذلك DikuMUD ومتغيراتها) مليئة بمشاكل الأداء بسبب القيود الموجودة في وقت إنشائها.

عدم وجود خيوط

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

كل جزء من الكود يبطئ معالجة علامة واحدة. وإذا فرض أي حساب على المعالجة أن تمتد لفترة أطول من علامة واحدة ، فإن MUD يتأخر ، ويؤثر على كل لاعب متصل.

خلال "علامة" واحدة (زيادة في الساعة الداخلية تتعقب تقدم جميع أحداث اللعبة) ، يجب أن يعالج كود مصدر MUD كل حدث لعبة لكل مقبس متصل. بعبارة أخرى: كل جزء من الكود يبطئ معالجة علامة واحدة. وإذا فرض أي حساب على المعالجة أن تمتد لفترة أطول من علامة واحدة ، فإن MUD يتأخر ، ويؤثر على كل لاعب متصل.

مع هذا التأخير ، تصبح اللعبة على الفور أقل تفاعلاً. ينظر اللاعبون بلا حول ولا قوة بينما تموت شخصياتهم ، مع بقاء أوامرهم الخاصة دون معالجة.

إدخال SillyMUD

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

ماذا كنت أرث؟

الكود المصدري SillyMUD مشابه لتلك الموجودة في C MUDs التاريخية الأخرى من حيث أنه يقتصر على ما يقرب من 50 لاعبًا متزامنًا (64 ، على وجه الدقة ، بناءً على الكود المصدري).

ومع ذلك ، لاحظت أنه تم تعديل شفرة المصدر لأسباب تتعلق بالأداء (أي لدفع قيود المشغل المتزامنة). خاصة:

  • يفتقد كود المصدر للبحث عن اسم المجال على عنوان IP للاتصال ، غائبًا بسبب التأخير الذي يفرضه البحث عن اسم المجال (عادةً ، يريد MUD الأقدم البحث عن اسم المجال لتسهيل حظر المستخدمين الضارين).
  • تم تعطيل أمر "تبرع" في التعليمات البرمجية المصدر (وهو أمر غير معتاد بعض الشيء) بسبب إمكانية إنشاء قوائم طويلة مرتبطة بالعناصر المتبرع بها والتي تتطلب بعد ذلك عمليات اجتياز قائمة مكثفة للمعالجة. هذا ، بدوره ، يضر بأداء اللعبة لجميع اللاعبين الآخرين (الخيط الفردي ، تذكر؟).

تقديم CloudI

تمت مناقشة CloudI سابقًا كحل لتطوير متعدد اللغات نظرًا لما يوفره من تحمل للأخطاء وقابلية للتوسع.

توفر CloudI تجريدًا للخدمة (لتوفير هندسة موجهة للخدمة (SOA)) في Erlang و C / C ++ و Java و Python و Ruby ، ​​مع الحفاظ على أعطال البرامج معزولة داخل إطار عمل CloudI. يتم توفير التسامح مع الأخطاء من خلال تطبيق Erlang الخاص بـ CloudI ، بالاعتماد على ميزات Erlang المتسامحة مع الأخطاء وتنفيذها لنموذج الممثل. هذا التسامح مع الخطأ هو ميزة أساسية لتطبيق CloudI's Erlang ، حيث تحتوي جميع البرامج على أخطاء.

توفر CloudI أيضًا خادم تطبيق للتحكم في عمر تنفيذ الخدمة وإنشاء عمليات الخدمة (إما كعمليات نظام تشغيل للغات البرمجة غير Erlang أو كعمليات Erlang للخدمات المنفذة في Erlang) بحيث يتم تنفيذ الخدمة دون التأثير على الحالة الخارجية الموثوقية. لمزيد من المعلومات ، انظر رسالتي السابقة.

كيف يمكن لـ CloudI تحديث MUD القديم المستند إلى النصوص؟

يوفر رمز مصدر C MUD التاريخي فرصة مثيرة للاهتمام لتكامل CloudI نظرًا لمشاكل الموثوقية:

  • يؤثر استقرار خادم اللعبة بشكل مباشر على جاذبية أي آليات لعبة.
  • تركيز تطوير البرامج على إصلاح أخطاء استقرار الخادم يحد من حجم ونطاق اللعبة الناتجة.

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

ما هي التغييرات المطلوبة؟

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

باستخدام CloudI ، تمكنت من الاحتفاظ بالشفرة المصدر ذات الخيط الفردي مع الاستمرار في توفير قابلية توسيع اتصال المقبس.

كان هدفي هو الحفاظ على وظائف شفرة المصدر القديمة أثناء تكييفها للاستخدام الحديث.

لنراجع التغييرات اللازمة:

إخراج وحدة التحكم

كان التخزين المؤقت لإخراج وحدة تحكم SillyMUD (عرض طرفي ، غالبًا ما يكون متصلًا بـ Telnet) في مكانه بالفعل ، ولكن بعض استخدام واصف الملف المباشر يتطلب تخزينًا مؤقتًا (بحيث يمكن أن يصبح إخراج وحدة التحكم استجابة لطلب خدمة CloudI).

التعامل مع المقبس

اعتمدت معالجة المقبس في التعليمات البرمجية الأصلية على استدعاء دالة select() لاكتشاف المدخلات والأخطاء وفرصة الإخراج ، بالإضافة إلى التوقف مؤقتًا لعلامة لعبة تبلغ 250 مللي ثانية قبل التعامل مع أحداث اللعبة المعلقة.

يعتمد تكامل CloudI SillyMUD على طلبات الخدمة الواردة للإدخال أثناء التوقف مؤقتًا باستخدام وظيفة cloudi_poll الخاصة بواجهة برمجة تطبيقات C cloudi_poll (لمدة 250 مللي ثانية قبل التعامل مع أحداث اللعبة المعلقة نفسها). يتم تشغيل الكود المصدري SillyMUD بسهولة داخل CloudI كخدمة CloudI بعد تكامله مع C CloudI API (على الرغم من أن CloudI يوفر كلا من واجهات برمجة تطبيقات C و C ++ ، باستخدام واجهة برمجة تطبيقات C أسهل للتكامل مع شفرة مصدر SillyMUD's C).

الاشتراكات

يشترك تكامل CloudI في ثلاثة أنماط رئيسية لاسم الخدمة للتعامل مع أحداث الاتصال وقطع الاتصال وألعاب اللعب. تأتي أنماط الاسم هذه من استدعاء C CloudI API للاشتراك في كود مصدر التكامل. وفقًا لذلك ، إما اتصالات WebSocket أو اتصالات Telnet لها وجهات اسم الخدمة لإرسال طلبات الخدمة عند إنشاء الاتصالات.

يتم توفير دعم WebSocket و Telnet في CloudI بواسطة خدمات CloudI الداخلية ( cloudi_service_http_cowboy لدعم WebSocket و cloudi_service_tcp لدعم Telnet). نظرًا لأن خدمات CloudI الداخلية مكتوبة بلغة Erlang ، فإنها قادرة على الاستفادة من قابلية التوسع الهائلة لشركة Erlang ، بينما تستخدم في نفس الوقت تجريد خدمة CloudI الذي يوفر وظائف CloudI API.

للمضي قدما

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

أدت إزالة معالجة المقبس منخفض المستوى إلى معالجة مشكلة قابلية التوسع الأساسية.

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

ما مدى تحسن الطين؟

مع تكامل CloudI ، تم قياس عدد الاتصالات بثلاثة أوامر من حيث الحجم مع توفير التسامح مع الأخطاء وزيادة كفاءة نفس طريقة اللعب القديمة.

كانت هناك ثلاثة مجالات رئيسية للتحسين:

  1. التسامح مع الخطأ. من خلال تكامل خدمة SillyMUD CloudI المحدث ، يوفر عزل أخطاء المقبس وزمن الانتقال من شفرة مصدر SillyMUD درجة من التسامح مع الخطأ.
  2. قابلية الاتصال. باستخدام خدمات CloudI الداخلية ، يمكن للقيود المفروضة على مستخدمي SillyMUD المتزامنين الانتقال بسهولة من 64 (تاريخيًا) إلى 16384 مستخدمًا (بدون مشاكل زمن الوصول!) .
  3. الكفاءة والأداء. مع معالجة الاتصال التي تتم داخل CloudI بدلاً من شفرة مصدر SillyMUD ذات الخيط الواحد ، يتم تحسين كفاءة شفرة مصدر تشغيل SillyMUD بشكل طبيعي ويمكنها التعامل مع حمولة أعلى.

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

الصورة الاكبر

لقد وفرت Erlang وقت تشغيل بنسبة 99.9999999٪ (أقل من 31.536 مللي ثانية من وقت التعطل سنويًا) لأنظمة الإنتاج. مع CloudI ، نوفر نفس الموثوقية للغات وأنظمة البرمجة الأخرى.

إلى جانب إثبات جدوى هذا النهج لتحسين شفرة مصدر خادم الألعاب القديمة الراكدة (تم تعديل SillyMUD آخر مرة منذ أكثر من 20 عامًا في 1993!) ، يوضح هذا المشروع على مستوى أوسع كيف يمكن الاستفادة من Erlang و CloudI لتحديث التطبيقات القديمة وتقديم أخطاء - التسامح وتحسين الأداء والتوافر العالي بشكل عام. تحمل هذه النتائج إمكانات واعدة لتكييف الكود القديم مع القرن الحادي والعشرين دون الحاجة إلى إصلاح شامل للبرامج.