خرطوشة Tarantool: تمزيق لوا الخلفي في ثلاثة خطوط



في Mail.ru Group ، لدينا Tarantool - هذا هو خادم التطبيقات على Lua ، والذي يحتوي أيضًا على قاعدة بيانات (أو العكس؟). إنه سريع وبارد ، لكن قدرات خادم واحد لا تزال غير محدودة. التحجيم العمودي ليس أيضًا حلاً سحريًا ، لذلك يحتوي Tarantool على أدوات للتحجيم الأفقي - وحدة vshard [1] . يسمح لك بمشاركة البيانات عبر عدة خوادم ، ولكن يجب عليك العبث بها لتكوينها وربط منطق العمل.

خبر سار: قمنا بجمع المخاريط (على سبيل المثال [2] ، [3] ) وتخلصنا من إطار آخر من شأنه تبسيط حل هذه المشكلة بشكل كبير.

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

وما هي في الواقع المشكلة؟


لدينا رتيلاء ، هناك vshard - أكثر ما يمكن أن تريد؟

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

تدير Cartridge نفسها التكوين vshard ؛ وتقوم بذلك بناءً على التكوين الموزع الخاص بها . في جوهره ، هذا ملف YAML بسيط ، يتم تخزين نسخة منه في كل مثيل من Tarantool. يكمن التبسيط في حقيقة أن الإطار نفسه يراقب التكوين الخاص به وبحيث يكون هو نفسه في كل مكان.

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

لقد حللنا هذه المشكلات مرارًا وتكرارًا ، وفي مرحلة ما تمكنا من تطوير نهج لتبسيط العمل مع التطبيق طوال دورة حياته الكاملة: الإنشاء ، التطوير ، الاختبار ، CI / CD ، الصيانة.

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

الملامح الرئيسية لخرطوشة Tarantool:

  • تزامن الكتلة الآلي.
  • توسيع وظائف التطبيق بأدوار جديدة ؛
  • تطوير التطبيق ونشر قالب.
  • المدمج في تقاسم التلقائي.
  • التكامل مع إطار اختبار Luatest ؛
  • إدارة الكتلة باستخدام WebUI و API ؛
  • أدوات التغليف والنشر.

مرحبا العالم!


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

$ tarantoolctl rocks install cartridge-cli $ export PATH=$PWD/.rocks/bin/:$PATH 

سيقوم هذان الأمران بتثبيت الأدوات المساعدة لسطر الأوامر وتتيح لك إنشاء التطبيق الأول من القالب:

 $ cartridge create --name myapp 

وهنا ما حصلنا عليه:

 myapp/ ├── .git/ ├── .gitignore ├── app/roles/custom.lua ├── deps.sh ├── init.lua ├── myapp-scm-1.rockspec ├── test │ ├── helper │ │ ├── integration.lua │ │ └── unit.lua │ ├── helper.lua │ ├── integration/api_test.lua │ └── unit/sample_test.lua └── tmp/ 

هذا هو مستودع بوابة مع الانتهاء من "مرحبا ، العالم!" التطبيق. دعونا نحاول تشغيله على الفور ، قبل تثبيت التبعيات (بما في ذلك الإطار نفسه):

 $ tarantoolctl rocks make $ ./init.lua --http-port 8080 

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

تطوير التطبيق


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



نبدأ في رسم رسم تخطيطي ، ووضع ثلاثة مكونات عليه: البوابة والتخزين والجدولة. نحن نعمل على الهندسة المعمارية كذلك. بما أننا نستخدم vshard للتخزين ، فإننا نضيف vshard-router و vshard-storage إلى المخطط. لن تتمكن البوابة أو المجدول من الوصول مباشرة إلى المستودع ، فهناك جهاز توجيه لهذا ، تم إنشاؤه لذلك.



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



الحفاظ على vshard- جهاز التوجيه والعبارة في حالات منفصلة لا معنى له. لماذا نحتاج إلى الانتقال عبر الشبكة مرة أخرى ، إذا كانت هذه هي مسؤولية الموجه بالفعل؟ يجب أن تعمل في نفس العملية. هذا هو ، في عملية واحدة ، تتم تهيئة كل من البوابة و vshard.router.cfg ، ودعهما يتفاعلان محليًا.

كان من المناسب العمل مع ثلاثة مكونات في مرحلة التصميم ، لكن كمطور ، أثناء كتابة التعليمات البرمجية ، لا أريد التفكير في إطلاق ثلاث حالات من Tarnatool. أحتاج إلى تشغيل الاختبارات والتحقق من أنني كتبت العبارة بشكل صحيح. أو ربما أريد عرض ميزة لزملائي. لماذا يجب أن أعاني مع نشر ثلاث نسخ؟ هكذا ولد مفهوم الأدوار. الدور هو وحدة Loach العادية التي تتم إدارة دورة حياتها بواسطة Cartridge. في هذا المثال ، هناك أربعة منهم - البوابة ، جهاز التوجيه ، التخزين ، المجدول. في مشروع آخر ، قد يكون هناك المزيد. جميع الأدوار يمكن إطلاقها في عملية واحدة ، وهذا سيكون كافيا.



وعندما يتعلق الأمر بالنشر إلى التدريج أو التشغيل ، سنقوم بتعيين كل مجموعة من الأدوار لكل عملية Tarantool ، اعتمادًا على إمكانيات الأجهزة:



إدارة الطوبولوجيا


يجب تخزين المعلومات حول المكان الذي يتم فيه تشغيل الأدوار في مكان ما. وهذا "في مكان ما" هو التكوين الموزع الذي ذكرته أعلاه. الشيء الأكثر أهمية في ذلك هو طوبولوجيا الكتلة. فيما يلي 3 مجموعات نسخ متماثل لـ 5 عمليات Tarantool:



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

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



دور الحياة


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

 function init() function validate_config() function apply_config() function stop() 

كل دور لديه وظيفة init . يطلق عليه مرة واحدة ، إما عند تمكين الدور ، أو عند إعادة تشغيل Tarantool. من المريح ، على سبيل المثال ، تهيئة box.space.create ، أو يمكن لجدولة بدء بعض الألياف الخلفية ، والتي ستقوم بالعمل على فترات زمنية معينة.

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

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

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

يمكن أن تتفاعل الأدوار مع بعضها البعض. لقد اعتدنا على كتابة المكالمات الوظيفية في لوا ، ولكن قد يحدث أنه ليس لدينا الدور الذي نحتاجه في هذه العملية. لتسهيل الوصول إلى الشبكة ، نستخدم الوحدة النمطية rpc (استدعاء الإجراء عن بُعد) ، والتي بنيت على أساس netbox القياسي المدمج في Tarantool. يمكن أن يكون هذا مفيدًا ، على سبيل المثال ، إذا أرادت بوابتك أن تطلب من المجدول مباشرة القيام بالمهمة الآن ، بدلاً من الانتظار ليوم واحد.

نقطة أخرى مهمة هي ضمان التسامح مع الخطأ. تستخدم الخرطوشة بروتوكول SWIM [4] لمراقبة الصحة. باختصار ، تتبادل العمليات "شائعات" مع بعضها البعض عبر UDP - كل عملية تخبر جيرانها بأحدث الأخبار ، وأنها تستجيب. إذا لم تتم الإجابة ، يبدأ تارانتول في الشك في أن هناك خطأ ما ، وبعد فترة من الوقت يتلو الموت ويبدأ في إخبار الجميع حول هذا الخبر.



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



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

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

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

أدوات النشر


وعدت أن أظهر كيف تساعد Cartridge في نشر التطبيقات. لتسهيل الحياة على الآخرين ، حزم إطار حزم RPM:

 $ cartridge pack rpm myapp #    ./myapp-0.1.0-1.rpm $ sudo yum install ./myapp-0.1.0-1.rpm 

تحتوي الحزمة المثبتة على كل ما تحتاجه تقريبًا: كلاً من التطبيق وتبعيات lauch المثبتة. سيأتي Tarantool أيضًا إلى الخادم كاعتماد على حزمة RPM ، وتكون خدمتنا جاهزة للإطلاق. يتم ذلك من خلال systemd ، لكن أولاً تحتاج إلى كتابة القليل من التكوين. كحد أدنى ، حدد URI لكل عملية. ثلاثة على سبيل المثال يكفي.

 $ sudo tee /etc/tarantool/conf.d/demo.yml <<CONFIG myapp.router: {"advertise_uri": "localhost:3301", "http_port": 8080} myapp.storage_A: {"advertise_uri": "localhost:3302", "http_enabled": False} myapp.storage_B: {"advertise_uri": "localhost:3303", "http_enabled": False} CONFIG 

هناك فارق بسيط للاهتمام هنا. بدلاً من تحديد منفذ البروتوكول الثنائي فقط ، نحدد العنوان العام للعملية بأكملها بما في ذلك اسم المضيف. يعد ذلك ضروريًا حتى تعرف عقد الكتلة كيفية الاتصال مع بعضها البعض. من المستحسن استخدام العنوان 0.0.0.0 كـ advertise_uri ، يجب أن يكون عنوان IP خارجي ، وليس مأخذ ربط. وبدون ذلك ، لن ينجح أي شيء ، لذلك لن تسمح Cartridge ببساطة بتشغيل العقدة التي تحتوي على advertise_uri الخطأ.

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

 $ sudo systemctl start myapp@router $ sudo systemctl start myapp@storage_A $ sudo systemctl start myapp@storage_B 

في التكوين ، حددنا منفذ HTTP الذي تخدم عليه Cartridge واجهة الويب - 8080. دعنا نذهب فوقه ونرى:



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

صب كوب من مشروبك المفضل واسترخ بعد أسبوع عمل طويل. يمكن استغلال التطبيق.



النتائج


وما هي النتائج؟ جرب ، استخدم ، اترك التعليق ، ابدأ التذاكر على جيثب.

مراجع


[1] Tarantool »2.2» مرجع »مرجع الصخور» وحدة vshard

[2] كيف طبقنا جوهر أعمال الاستثمار في بنك ألفا على أساس Tarantool

[3] بنية إعداد الفواتير من الجيل التالي: الانتقال إلى Tarantool

[4] SWIM - بروتوكول بناء الكتلة

[5] جيثب - تارانتول / خرطوشة CLI

[6] جيثب - تارانتول / خرطوشة

Source: https://habr.com/ru/post/ar465503/


All Articles