كيف يتعامل Node.js مع آلاف الطلبات
يقول الناس إن Node.js يعمل بخيط معالجة واحد (single-threaded).
ومع ذلك، فإنه يتعامل مع آلاف الطلبات، ويقرأ الملفات، ويجري استدعاءات API دون توقف.
كيف يعمل ذلك؟
الإجابة هي libuv.
libuv هي مكتبة مكتوبة بلغة C. تمنح Node.js قدرات الإدخال والإخراج (I/O) غير المتزامنة وغير الحاجبة (asynchronous and non-blocking). لا تستطيع JavaScript قراءة الملفات أو إدارة مقابس الشبكة (network sockets) بمفردها. يستخدم Node.js مكتبة libuv للتواصل مع نظام التشغيل الخاص بك.
بدون libuv، ستتوقف JavaScript في كل مرة تقرأ فيها ملفاً، مما يجعل تطبيقك غير مستجيب.
بوجود libuv، تتم قراءة الملف في الخلفية، بينما تستمر JavaScript في تشغيل الأكواد الأخرى.
مثال:
console.log("Start");
fs.readFile("data.txt", "utf8", (err, data) => {
console.log(data);
});
console.log("End");
المخرجات: Start End (محتويات الملف)
يقوم Node.js بطباعة "End" قبل انتهاء قراءة الملف؛ فهو لا ينتظر.
كيف تدير libuv الكود الخاص بك:
• حلقة الأحداث (The Event Loop): تقوم libuv بتشغيل الحلقة التي تتحقق مما إذا كانت المهام قد اكتملت، وتضع دوال الاستدعاء (callbacks) في طابور عند انتهاء المهام. • مجمع الخيوط (Thread Pool): تستخدم JavaScript خيطاً واحداً، بينما تستخدم libuv مجمعاً من خيوط العمل (worker threads). افتراضياً، يحتوي هذا المجمع على 4 خيوط. تتعامل هذه الخيوط مع المهام الثقيلة مثل:
- عمليات نظام الملفات
- عمليات البحث في DNS
- الضغط
- التشفير
• الشبكات (Networking): تدير libuv مقابس HTTP وTCP وUDP، مما يسمح للخوادم بالتعامل مع العديد من الاتصالات في وقت واحد.
• المؤقتات (Timers): تتعامل libuv مع
setTimeoutوsetInterval.
يعمل تدفق التنفيذ على النحو التالي:
- تقوم JavaScript بتشغيل الكود الخاص بك.
- تأخذ libuv المهام الثقيلة إلى الخلفية.
- تستمر JavaScript في الانتقال إلى السطر التالي.
- تقوم libuv بإخطار حلقة الأحداث (Event Loop) عند انتهاء المهمة.
- تقوم حلقة الأحداث بتشغيل دالة الاستدعاء (callback) الخاصة بك.
تخيل محل بيتزا.
بدون libuv، ستقف عند المنصة وتسأل "هل طعامي جاهز؟" كل عشر ثوانٍ، مما يؤدي إلى تعطيل الطابور.
بوجود libuv، تطلب طلبك، ثم تجلس وتنتظر إشعاراً. تظل حراً للقيام بأشياء أخرى حتى تصبح البيتزا جاهزة.
ملخص:
• تنفيذ JavaScript: محرك V8 Engine • حلقة الأحداث: libuv • عمليات الإدخال والإخراج للملفات: libuv • الشبكة: libuv • المؤقتات: libuv
libuv هو المحرك الذي يحافظ على سرعة Node.js.
