it-swarm.asia

لماذا هو Node.js واحد الخيوط؟

في PHP (أو Java/ASP.NET/Ruby) ، يتم إنشاء مثيل لكل طلب عميل في سلسلة رسائل جديدة. لكن في Node.js ، يعمل جميع العملاء على نفس مؤشر الترابط (يمكنهم حتى مشاركة نفس المتغيرات!) وأنا أفهم أن عمليات الإدخال/الإخراج تستند إلى الأحداث بحيث لا تحظر حلقة مؤشر الترابط الرئيسية.

ما لا أفهمه هو لماذا اختار مؤلف Node أن يكون مترابط واحد؟ يجعل الأمور صعبة. على سبيل المثال ، لا يمكنني تشغيل وظيفة مكثفة لوحدة المعالجة المركزية لأنه يحظر سلسلة الرسائل الرئيسية (ويتم حظر طلبات العميل الجديدة) لذلك أحتاج إلى إنشاء عملية (مما يعني أنني بحاجة إلى إنشاء ملف JavaScript منفصل وتنفيذ عملية عقدة أخرى عليها) ). ومع ذلك ، في PHP لا تؤدي المهام المكثفة في وحدة المعالجة المركزية إلى حظر عملاء آخرين لأنني ذكرت كما ذكر كل عميل على مؤشر ترابط مختلف. ما هي مزاياها مقارنة بخوادم الويب متعددة الخيوط؟

ملاحظة: لقد استخدمت المجموعات للتغلب على هذا ، ولكنها ليست جميلة.

228
foreyez

تم إنشاء Node.js بشكل صريح كتجربة في معالجة المزامنة. كانت النظرية أن القيام بالمعالجة غير المتزامنة في سلسلة رسائل واحدة يمكن أن يوفر أداءً وإمكانيةً أكبر في ظل تحميلات الويب المعتادة مقارنة بالتنفيذ المعتمد على سلاسل الرسائل.

وتعلم ماذا؟ في رأيي أن هذه النظرية قد تم إثباتها. يمكن لتطبيق node.js الذي لا يقوم بأشياء مكثفة لوحدة المعالجة المركزية تشغيل آلاف الاتصالات المتزامنة أكثر من Apache أو IIS أو خوادم أخرى قائمة على سلاسل الرسائل.

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

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

255
Chris Tavares

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

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

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

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

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

55
Kazaag

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

عند نقطة واحدة (0.7) ، حاول المؤلفون تقديم عزلات كوسيلة لتنفيذ مؤشرات ترابط متعددة للحساب ، ولكن تمت إزالتها في النهاية: https://groups.google.com/forum/#!msg/nodejs/zLzuo292hX0/F7gqfUiKi2sJ

28
SheetJS