إجابة بسيطة: Node.js عبارة عن خيط مفرد ويقسم هذا الخيط المفرد لمحاكاة التزامن، بينما يستفيد Elixir من التزامن والتوازي، الأصلي، لـ BEAM، جهاز Erlang الظاهري، لتنفيذ العمليات في وقت واحد.
أدناه، سوف نفهم هذا الاختلاف بمزيد من التعمق، ونستكشف مفهومين رئيسيين: حلقة أحداث Node.js وBEAM VM وOTP من Elixir. تعتبر هذه العناصر ضرورية لفهم كيفية تعامل كل تقنية مع تنفيذ المهام غير المتزامنة وكيف يؤثر ذلك على الأداء وقابلية التوسع في التطبيقات المختلفة.
1. ما هي حلقة الحدث؟
يعمل Node.js على مؤشر ترابط رئيسي واحد ويستخدم آلية تسمى حلقة الأحداث لإدارة العمليات غير المتزامنة. المفهوم الأساسي هو أنه يتحقق من المهام المعلقة التي ستتم معالجتها، مثل عمليات الإدخال/الإخراج والوعود وعمليات الاسترجاعات، وتنفيذها عندما تكون جاهزة.
1.1 كيف يتم التنفيذ عمليًا:
عند بدء عملية غير متزامنة (على سبيل المثال، استعلام إلى واجهة برمجة التطبيقات)، يتم تفويضها إلى libuv. وفي الوقت نفسه، تستمر حلقة الحدث في قبول الاتصالات الأخرى.
عند انتهاء العملية غير المتزامنة، يعيد libuv النتيجة إلى قائمة انتظار الأحداث، ثم تضع حلقة الحدث رد الاتصال المرتبط بالعملية، على مكدس الاستدعاءات.
1.2 حدود حلقة الحدث:
- إذا كانت هناك مهمة تستغرق وقتًا طويلاً أو تستهلك الكثير من وحدة المعالجة المركزية في مكدس الاستدعاءات، فيمكن أن تمنع معالجة العمليات الأخرى، مما يقلل الكفاءة.
- التزامن محدود حيث أن كل شيء يعمل على موضوع رئيسي واحد.
2. BEAM VM وOTP
تم تصميم Elixir على BEAM VM، وهو نفس الجهاز الظاهري الذي يشغل Erlang، والمعروف بقدرته على التعامل مع التزامن العالي والمرونة. على عكس Node.js، لا يعتمد Elixir على خيط واحد. وبدلاً من ذلك، فإنه يستخدم عمليات خفيفة الوزن ومعزولة للغاية يديرها BEAM.
2.1 كيف يتم التنفيذ عمليًا:
كل عملية في Elixir مستقلة، مما يعني أنها لا تتشارك في الذاكرة ولا تحجب بعضها البعض.-
تتم إدارة هذه العمليات بواسطة BEAM، الذي يمكنه إنشاء وإدارة ملايين العمليات في وقت واحد، وتوزيع الحمل على جميع مراكز وحدة المعالجة المركزية المتاحة.-
بالإضافة إلى ذلك، يأتي Elixir مع OTP (منصة الاتصالات المفتوحة)، التي توفر مجموعة من المكتبات والأدوات لبناء أنظمة قوية وموزعة.-
2.2 مزايا BEAM وOTP:
قابلية التوسع: يمكن لـ BEAM توزيع العمليات عبر جميع مراكز وحدة المعالجة المركزية، مما يزيد من استخدام الموارد إلى الحد الأقصى.-
المرونة: إذا فشلت عملية ما، فلن يؤثر ذلك على العمليات الأخرى. وهذا يسمح لك ببناء أنظمة تتحمل الأخطاء.-
المنافسة الحقيقية: على عكس حلقة الأحداث، التي تقتصر على خيط واحد، يمكن لـ Elixir تشغيل العمليات بالتوازي، مع الاستفادة من نوى وحدة المعالجة المركزية المتعددة.-
3. مقارنة Node.js و Elixir في الممارسة العملية
لنتخيل خادمًا يحتاج إلى التعامل مع آلاف الاتصالات المتزامنة، حيث يؤدي كل منها عمليات غير متزامنة وبعض العمليات الثقيلة التي تستغرق وقتًا طويلاً.
3.1 مع Node.js:
الخادم فعال إلى حد ما، ولكن مع تراكم العمليات الثقيلة، تبدأ حلقة الحدث في التحميل الزائد. على الرغم من أن الاستخدام الجيد للموارد المتاحة في - JS وNode يمكن أن يساعد كثيرًا في الأداء: مثل الاستخدام الصحيح للموارد غير المتزامنة/الانتظار و/أو ثم/التقاط والموارد المضمنة مثل العقدة lib:cluster
يمكن أن يؤدي هذا إلى تأخير في الاستجابة للاتصالات الجديدة، مما يؤدي إلى حدوث ضرر كبير في الأداء.-
3.2 مع الإكسير:
يمكن إدارة كل اتصال من خلال عملية منفصلة. يمكن إدارة عمليات الإدخال/الإخراج والحسابات وحتى حالات الفشل بشكل منفصل.-
تقوم BEAM بتوزيع الحمل بكفاءة، مما يضمن استمرار النظام في العمل دون مشاكل كبيرة، حتى في ظل ارتفاع الطلب.-
إذا لزم الأمر، فمن الممكن التواصل بين العمليات عبر الرسائل.-
آلية الجدولة الوقائية لـ BEAM.-
خاتمة
Node.js هي أداة ممتازة للعديد من التطبيقات، خاصة تلك التي تتعامل مع العمليات البسيطة غير المتزامنة ولا تتطلب معالجة مكثفة لوحدة المعالجة المركزية. ومع ذلك، فإن نموذج التزامن القائم على خيط واحد يمكن أن يشكل عنق الزجاجة في سيناريوهات أكثر تعقيدًا.
يوفر Elixir، مع BEAM VM والدعم الأصلي للعمليات خفيفة الوزن والتزامن الهائل، بديلاً قويًا وفعالاً للأنظمة التي تحتاج إلى التعامل مع عدد كبير من العمليات المتزامنة وتوزيع الحمل بين سلاسل
وحدة المعالجة المركزية المتعددة. إذا كنت بحاجة إلى المرونة وقابلية التوسع والتزامن العالي، فإن Elixir هو الخيار المناسب.
على الرغم من أن عنوان هذه المقالة جريء في الإشارة إلى أن Elixir وBEAM يتفوقان على Node.js في المعالجة غير المتزامنة، فمن المهم أن ندرك أن هناك اختلافات كبيرة بين هذه التقنيات. يجب أن يأخذ القرار بشأن أي واحد سيتم استخدامه في الاعتبار مجموعة متنوعة من العوامل، وليس فقط التزامن والتوازي الذي تمت مناقشته هنا. تلعب جوانب مثل النظام البيئي، وإلمام الفريق باللغة، ومتطلبات المشروع المحددة، وطبيعة المهام التي سيتم تنفيذها دورًا حاسمًا في اختيار أفضل أداة للوظيفة. ففي نهاية المطاف، كل سيناريو له خصوصياته، ويجب أن يتم اختيار التكنولوجيا بنظرة شمولية، مع الأخذ بعين الاعتبار جميع احتياجات المشروع وتحدياته.
فهرس
المواضيع:
الخيوط هي أصغر وحدات التنفيذ في البرنامج. في العديد من أنظمة التشغيل، يمكن أن تحتوي العملية على عدة سلاسل عمليات، كل منها ينفذ جزءًا مختلفًا من البرنامج. يمكن للسلاسل مشاركة الذاكرة والموارد، ولكن هذا قد يؤدي إلى مشكلات في التزامن مثل حالات السباق.
مسابقة:
التزامن هو قدرة النظام على التعامل مع مهام متعددة في نفس الوقت. في النظام المتزامن، يمكن أن تتقدم مهام متعددة بشكل مستقل حتى لو لم تكن قيد التشغيل في وقت واحد. BEAM، على سبيل المثال، تدير العمليات المتنافسة التي تعمل بشكل مستقل.
حلقة الحدث:
حلقة الحدث هي نمط تصميم يستخدم في أنظمة مثل Node.js لإدارة العمليات غير المتزامنة. إنه يعمل في خيط واحد، وينفذ المهام بشكل دوري، ويستجيب لأحداث مثل الإدخال/الإخراج والتنفيذ غير المتزامن، مما يضمن استمرار البرنامج في الاستجابة أثناء انتظار العمليات الطويلة.
التوازي:
التوازي هو التنفيذ المتزامن لمهام متعددة على مراكز مختلفة لوحدة المعالجة المركزية. على عكس التزامن، الذي يشير إلى إدارة المهام المتزامنة، يتضمن التوازي تنفيذ هذه المهام فعليًا في نفس الوقت. يقوم BEAM بتوزيع العمليات عبر مراكز متعددة لتحقيق أقصى قدر من التوازي.
عمليات خفيفة الوزن:
في BEAM، العمليات خفيفة الوزن هي وحدات تنفيذ أكثر كفاءة في الذاكرة ووحدة المعالجة المركزية من الخيوط التقليدية. وهي معزولة عن بعضها البعض وتتم إدارتها بواسطة BEAM، مما يسمح لك بإنشاء وإدارة الملايين من العمليات المتزامنة.
التخطيط الوقائي:
الجدولة الوقائية هي نظام لإدارة وقت التشغيل حيث يقوم نظام التشغيل أو الجهاز الظاهري بتعيين شرائح زمنية لكل عملية، مما يضمن عدم احتكار أي عملية لوحدة المعالجة المركزية. في BEAM، يضمن هذا أن جميع العمليات لديها فرصة ليتم تنفيذها بشكل عادل.
شعاع VM:
BEAM (آلة Erlang Abstract لـ Bogdan/Björn) هي الآلة الافتراضية التي تقوم بتشغيل كود Erlang و Elixir. وهي معروفة بقدرتها على إدارة العمليات خفيفة الوزن بكفاءة، ودعم التزامن والتوازي الهائلين، فضلاً عن توفير التسامح مع الأخطاء.
OTP (منصة الاتصالات المفتوحة):
OTP عبارة عن مجموعة من المكتبات وأنماط التصميم التي تأتي مع Erlang وElixir. فهو يوفر أدوات لبناء أنظمة متزامنة وموزعة ومتسامحة مع الأخطاء، مما يسهل تطوير تطبيقات قوية وقابلة للتطوير.
libuv
هي مكتبة مشتركة بين الأنظمة الأساسية توفر الدعم لعمليات الإدخال/الإخراج غير المتزامنة في Node.js. وهو مسؤول عن تنفيذ حلقة الأحداث واستخلاص وظائف نظام التشغيل، مثل عمليات الشبكة ونظام الملفات والخيوط. يسمح libuv لـ Node.js بتنفيذ المهام غير المتزامنة بكفاءة في سلسلة رسائل واحدة، وذلك باستخدام تجمع مؤشرات الترابط الداخلي لحظر العمليات، مما يضمن استمرارية حلقة الحدث الرئيسية.
عمليات الإدخال/الإخراج
تشير عمليات الإدخال/الإخراج (الإدخال/الإخراج) إلى أي تفاعل بين البرنامج والعالم الخارجي، مثل القراءة أو الكتابة إلى الملفات، أو الاتصال بالأجهزة، أو تبادل البيانات عبر الشبكة. يمكن أن تستغرق هذه العمليات وقتًا طويلاً، وفي العديد من الأنظمة، يتم تنفيذها بشكل غير متزامن لمنع البرنامج من الحظر أثناء انتظار اكتمال العملية.
مراجع
ايرلانج. التمهيدي القصير BEAM. مدونة إرلانج، 2020. متاحة على: https://www.erlang.org/blog/a-brief-beam-primer/. تم الوصول إليه في: 29 أغسطس. 2024.
ايرلانج. البدء مع Erlang [PDF]. Erlang.org. متاح على: https://erlang.org/download/erlang-book-part1.pdf. تم الوصول إليه في: 29 أغسطس. 2024.
عقدة الأطباء. دليل متحرك لحلقة أحداث Node.js. Dev.to, 2021. متاح على: https://dev.to/nodedoctors/an-animated-guide-to-nodejs-event-loop-3g62. تم الوصول إليه في: 29 أغسطس. 2024.
عقدة الأطباء. مراحل حلقة حدث Node.js المتحركة. Dev.to, 2022. متاح على: https://dev.to/nodedoctors/animated-nodejs-event-loop-phases-1mcp. تم الوصول إليه في: 29 أغسطس. 2024.
NODE.JS. تَجَمَّع. Node.js، 2023. متوفر على: https://nodejs.org/api/cluster.html. تم الوصول إليه في: 29 أغسطس. 2024.