العقدة، باعتبارها وقت تشغيل لجافا سكريبت على جانب الخادم، على إثراء سيناريوهات تطبيق جافا سكريبت بشكل كبير.
ومع ذلك، فإن وقت تشغيل Node.js نفسه عبارة عن صندوق أسود، ولا يمكننا إدراك حالة وقت التشغيل، ومن الصعب إعادة إنتاج المشكلات عبر الإنترنت.
ولذلك، فإن مراقبة الأداء هي حجر الزاوية في "التشغيل العادي" لتطبيقات Node.js. لا يمكن مراقبة مؤشرات وقت التشغيل المختلفة في أي وقت فحسب، بل يمكن أن تساعد أيضًا في استكشاف مشكلات السيناريو غير الطبيعية وإصلاحها.
يمكن تقسيم مراقبة أداءإلى قسمين:
جمع وعرض مؤشرات الأداء
التقاط وتحليل بيانات الأداء
مثل QPS، وHTTP البطيء، وسجلات ارتباط معالجة الأعمال، وما إلى ذلك.من الصورة أعلاه، يمكنك رؤية مزايا وعيوب حلول مراقبة أداء Node.js الثلاثة الحالية، وفيما يلي مقدمة موجزة لتكوين هذه الحلول الثلاثة:
Prometheus
AliNode.
Alinode هو وقت تشغيل ممتد متوافق مع العقد الرسمية، ويوفر بعض الوظائف الإضافية:
Agenthub هي عملية مقيمة تستخدم لجمع مؤشرات الأداء والإبلاغ عنها
تشكل الأدوات الملائمة لـ commdx حلقة مغلقة من المراقبة والعرض واللقطات والتحليل. الوصول مريح وبسيط، ولكن لا تزال هناك مخاطر عند توسيع وقت التشغيل
Easy-Monitor
Node.js Addon
لتنفيذيمكن الحصول على بيانات استهلاك وقت وحدة المعالجة المركزية للعملية الحالية من خلال process.cpuUsage()
وحدة القيمة المرجعة هي ميكروثانية
يمكن الحصول على بيانات تخصيص الذاكرة للعملية الحالية من خلال process.memoryUsage()
وحدة القيمة المرجعة هي بايت
كما يتبين من الشكل أعلاه، يتضمن rss
مقطع التعليمات البرمجية ( Code Segment
)، وذاكرة المكدس ( Stack
)، وذاكرة الكومة ( Heap
)
الحصول على بيانات التحليل لذاكرة الكومة v8 ومساحة الكومة من خلال v8.getHeapStatistics()
و v8.getHeapSpaceStatistics()
ويوضح الشكل التالي توزيع تكوين ذاكرة الكومة v8:
يتم أولاً تقسيم مساحة ذاكرة الكومة إلى مسافات، ويتم تقسيم المساحة إلى صفحات وفقًا لمحاذاة 1 ميجابايت.
الفضاء الجديد: فضاء الجيل الجديد، يستخدم لتخزين بعض بيانات الكائن مع دورة حياة قصيرة نسبيًا، مقسم إلى مساحتين (نوع الفضاء semi space
): from space
to space
الفضاء القديم : مساحة الجيل القديم المستخدمة لتخزين الكائنات التي يتم الترويج لها بواسطة New Space
Code Space: تخزن الكود القابل للتنفيذ الذي تم تجميعه بواسطة v8 JIT.
Map Space: يخزن كائن المؤشر للفئة المخفية التي يشير إليها الكائن
الكبيرة
: تستخدم لتخزين الكائنات التي يزيد حجمها عن 1 ميجا بايت والتي لا يمكن تخصيصها
للصفحات
Mark-Sweep-Compact
لإعادة تدوير الكائنات في الجيل القديمScavenge
لإعادة تدوير الكائنات في الجيل الجديدالفرضية: يتم تقسيم New space
إلى مساحتين للكائن: from
وإلى to
توقيت التشغيل: عندما تكون New space
ممتلئة.
الخطوات:
في from space
، قم بإجراء اجتياز العرض أولاً
واكتشف أن الكائن الباقي (الذي يمكن الوصول إليه)
Old space
to space
عند انتهاء النسخ، لا يوجد سوى كائنات باقية في to space
، ويتم إفراغها from space
،
ويتم التبادل from space
to space
، وتبدأ الجولة التالية Scavenge
مناسبة لإعادة التدوير المتكررة والذاكرة غير الكافية بالنسبة للأشياء الكبيرة، فإن استراتيجية المساحة مقابل الوقت النموذجية لها عيب إضاعة مساحة أكبر مرتين من
ثلاث خطوات: وضع العلامات والمسح والتنظيم
. توقيت التشغيل: عندما تكون Old space
ممتلئة.
الخطوات:
وضع العلامات (طريقة وضع العلامات ثلاثية الألوان).
marking queue
(مكدس صريح)، وقم بوضع علامة على هذه الكائنات باللون الرمادي.pop
الكائن من marking queue
ووضع علامة عليه باللون الأسود،push
إلى marking queue
الذاكرة
.
Old space
، بحيث تكون المساحة التي تم إخلاؤها مستمرة وكاملة،عندما يقوم الإصدار 8 في البداية بجمع البيانات المهملة، فإنه يحتاج إلى إيقاف البرنامج، وفحص الكومة بأكملها، واستعادة الذاكرة قبل إعادة تشغيل البرنامج. ويسمى هذا السلوك بالتوقف الكامل ( Stop-The-World
).
على الرغم من أن الكائنات النشطة في الجيل الجديد صغيرة الحجم ويتم إعادة تدويرها بشكل متكرر، إلا أن التوقف الكامل ليس له تأثير يذكر، إلا أن الكائنات الباقية في الجيل القديم كثيرة وكبيرة. والتوقف المؤقت الناتج عن وضع العلامات والتنظيف والفرز وما إلى ذلك. سيكون الأمر أكثر خطورة.
يشبه هذا المفهوم إلى حد ما بنية الألياف في إطار عمل React، فقط خلال وقت فراغ المتصفح سيجتاز شجرة الألياف لأداء المهام المقابلة. وإلا، فسيتم تأخير التنفيذ، مما يؤثر على مهام الخيط الرئيسي بأقل قدر ممكن وتجنب تأخر التطبيق وتحسين أداء التطبيق.
لأن الإصدار 8 لديه حد افتراضي للمساحة للأجيال الجديدة والقديمة
New space
32 ميجا بايت لأنظمة 64 بت و16 ميجا بايت لأنظمة 32 بتOld space
لأنظمة 64 بت 700M لأنظمة 32 بتلذلك، يتم توفير معلمتين node
لضبط الحد الأقصى للمساحة للأجيال الجديدة والقديمة
--max-semi-space-size
: تعيين الحد الأقصى لقيمة مساحة New Space
--max-old-space-size
: تعيين الحد الأقصى Old Space
node
ثلاث طرق لعرض سجلات GC:
--trace_gc
: يصف سطر السجل بإيجاز الوقت والنوع وتغييرات حجم الكومة وأسباب كل GC--trace_gc_verbose
: يعرض كل كومة V8 بعد كل GC حالة تفصيلية للمساحة--trace_gc_nvp
: معلومات مفصلة عن زوج المفتاح والقيمة لكل GC، بما في ذلك نوع GC، ووقت الإيقاف المؤقت، وتغييرات الذاكرة، وما إلى ذلك.نظرًا لأن سجل GC بدائي نسبيًا ويتطلب المعالجة الثانوية، يمكنك استخدام v8-gc- الذي تم تطويره بواسطة فريق AliNode، حيث
تأخذلقطة من ذاكرة الكومة لبرنامج قيد التشغيل ويمكن استخدامها لتحليل استهلاك الذاكرة وتغيير
.heapsnapshot
Heapsnapshot يتم إنشاؤها بالطرق التالية:
باستخدام heapdump
استخدام ملف تعريف الكومة v8
v8.getHeapSnapshot()
التي توفرها وحدة v8 المضمنة في Nodejs
v8.writeHeapSnapshot(fileName)
باستخدام v8-profiler-next
.heapsnapshot
الذاكرة على شريط أدوات Chrome devtools، وسيتم عرض النتائج كما هو موضح أدناه:
العرض الافتراضي هو عرض Summary
. هنا نحتاج إلى الانتباه إلى العمودين الموجودين في أقصى اليمين: Shallow Size
Retained Size
Retained Size
Shallow Size
إلى حجم الكائن نفسه المخصص في ذاكرة الكومة v8Shallow Size
لجميع الكائنات المشار إليها للكائنعندما يتبين أن Retained Size
كبير بشكل خاص، فقد يكون هناك تسرب للذاكرة داخل الكائن. يمكنك التوسع لتحديد موقع
Comparison
تحليل لقطات الكومة لفترتين مختلفتين يمكن استخدام عمود Delta
لتصفية الكائنات ذات أكبر تغييرات في الذاكرة.
بإجراء أخذ عينات من وحدة المعالجة المركزية التي تقوم بتشغيل البرنامج، والتي يمكن استخدامها لتحليل وقت وحدة المعالجة المركزية ونسبتها.
هناك عدة طرق لإنشاء ملف .cpuprofile
:
هذه مجموعة عينات لملف تعريف وحدة المعالجة المركزية مدتها 5 دقائق
يمكن عرضملف .cpuprofile
الذي تم إنشاؤه Javascript Profiler
العرض الافتراضي هو العرض Heavy
. هنا نرى عمودين: Self Time
Total Time
Self Time
: يمثل وقت تنفيذ هذه الوظيفة نفسها (باستثناء المكالمات الأخرى)Total Time
تنفيذ هذه الوظيفة (بما في ذلك المكالمات الأخرىTotal Time
Self Time
الوظيفة على عملية حسابية مكثفة لوحدة المعالجة المركزية (CPU) والتي تستغرق الكثير من الوقت، ويمكنك أيضًا إجراء المزيد من استكشاف الأخطاء وإصلاحها
يتعطل التطبيق وينتهي بشكل غير متوقع
.سيقوم النظام بتسجيله تلقائيًا. تعطل العملية معلومات تخصيص الذاكرة وعداد البرامج ومؤشر المكدس والمعلومات الأساسية الأخرى في تلك اللحظة لإنشاء
. ثلاث طرق لإنشاء ملفات .core
:
ulimit -c unlimited
يفتح حد kernelnode --abort-on-uncaught-exception
يمكن أن تؤدي إضافة هذه المعلمة عند بدء العقدة إلى إنشاء ملف أساسي عند حدوث استثناء لم يتم اكتشافه في التطبيقgcore <pid>
يتم إنشاءبعد الحصول على الملف .core
يمكن تحقيق التشخيص من خلال أدوات مثل mdb، وgdb، وlldb، وما إلى ذلك. السبب الفعلي لتعطل العملية
llnode `which node` -c /path/to/core/dump
يمكن ملاحظة من خلال المراقبة أن ذاكرة الكومة المؤقتة تستمر في الزيادة، لذلك هناك حاجة إلى لقطات الكومة لاستكشاف الأخطاء وإصلاحها
وفقًا heapsnapshot
يمكننا التحليل ومعرفة أن هناك كائنًا newThing
يحتفظ دائمًا بذاكرة كبيرة نسبيًا
theThing
unused
newThing
حالات replaceThing
الناتجة عن عمليات الإغلاق
الحالات التالية:
لذلك، في المواقف المذكورة أعلاه، يجب عليك التفكير بعناية فيما إذا كان سيتم إعادة تدوير الكائن الموجود في الذاكرة تلقائيًا أم لا لا يمكن إعادة تدويرها تلقائيًا، فأنت بحاجة إلى إعادة التدوير يدويًا، مثل ضبط الكائنات يدويًا على null
، وإزالة المؤقتات، وإلغاء ربط مستمعي الأحداث، وما إلى ذلك.
هذه المقالة، فقد قدمت مقدمة تفصيلية لنظام مراقبة أداء Node.js بأكمله.
أولاً، يعرض المشكلات التي يتم حلها عن طريق مراقبة الأداء ومكوناتها ومقارنة مزايا وعيوب الحلول السائدة.
بعد ذلك، يتم تقديم الجزأين الرئيسيين لمؤشرات الأداء وأدوات اللقطة بالتفصيل.
وأخيرًا، يتم إعادة إنتاج حالة تسرب الذاكرة البسيطة من خلال المراقبة والتحليل واستكشاف الأخطاء وإصلاحها، ويتم تلخيص حالات تسرب الذاكرة الشائعة والحلول.
آمل أن تساعد هذه المقالة الجميع على فهم نظام مراقبة أداء Node.js بالكامل.