6 دروس مستفادة من تجربة تحسين أداء خدمة Node.js

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



يستخدم Klarna نظام Node.js. المقال ، الذي نُنشر اليوم ترجمة له ، مكرس لتلك الدروس التي تمكن اختصاصيو الشركة من التعلم من تجربة تحسين أداء خدمتهم.

الدرس رقم 1: يمكن أن يوفر اختبار الأداء الثقة في أن سرعة النظام لا تتحلل مع كل إصدار


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

الدرس رقم 2: "إنهاء" الحمل بشكل مستقل ، يمكنك تحديد المشكلات حتى قبل أن تصل إلى الإنتاج


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


معلومات حول الوقت اللازم لمعالجة الطلب. تم اكتشاف نوع من المشاكل

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

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


شيء آخر يستحق الاهتمام هو أن مشاكل نظامنا تظهر بعد 2-3 دقائق من العمل تحت الحمل. في البداية ، أجرينا الاختبار لمدة دقيقتين فقط. ولم تظهر المشكلة إلا عند زيادة وقت تنفيذ الاختبار إلى 10 دقائق.

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


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

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

مورد آخر يحدد أداء مشاريع Node.js هو حلقة الحدث. مثلما هو مهم بالنسبة لنا لمعرفة مقدار الذاكرة التي تستخدمها العملية ، نحتاج إلى معرفة عدد "المهام" التي تحتاجها لمعالجة حلقة الحدث. يتم تنفيذ حلقة الحدث Node.js في مكتبة libuv C ++ ( هنا فيديو جيدة حول هذا الموضوع). يشار إلى "المهام" في هذه الوثيقة باسم "الطلب النشط". القياس المهم الآخر هو عدد "المقابض النشطة" التي تمثلها واصفات الملفات المفتوحة أو المقابس المستخدمة في عمليات Node.js. يمكن العثور على قائمة كاملة بأنواع الواصفات في وثائق libuv. نتيجة لذلك ، إذا كان الاختبار يستخدم 30 اتصالًا ، فيمكن توقع أن يحتوي النظام على 30 من الواصفات النشطة. يشير المؤشر الذي يصف عدد الطلبات النشطة إلى عدد العمليات التي تنتظر في صف واصف معين. ما هي هذه العمليات؟ على سبيل المثال ، عمليات القراءة / الكتابة. قائمة كاملة منهم يمكن العثور عليها هنا .

بعد تحليل مقاييس الخدمة ، أدركنا أن هناك خطأ ما هنا. بينما كان عدد الواصفات النشطة هو ما توقعناه (في هذا الاختبار - حوالي 30) ، كان عدد الطلبات النشطة مرتفعًا بشكل غير متناسب - عدة عشرات الآلاف.


واصفات نشطة وطلبات نشطة

صحيح أننا لم نعرف بعد أنواع الطلبات التي كانت في قائمة الانتظار. بعد تقسيم الاستعلامات النشطة إلى أنواع ، تم مسح الموقف قليلاً. وهي ، استفسارات UV_GETADDRINFO تبين أنها ملحوظة للغاية. يتم إنشاؤها عندما يحاول Node.js حل اسم DNS.

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

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


معلومات حول الوقت اللازم لمعالجة الطلب. نتيجة استخدام ذاكرة التخزين المؤقت DNS الخارجية

الدرس # 5: إجراء عمليات الإدخال / الإخراج في وضع الدفعي. مثل هذه العمليات ، حتى غير المتزامنة ، هي مستهلكين جادين للموارد.


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


معلومات حول الوقت اللازم لمعالجة الطلب. وكشف الاختبار زيادة حادة في الوقت اللازم لتشكيل الإجابات

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


معلومات حول الوقت اللازم لإنشاء رسائل لـ Kafka

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


معلومات حول الوقت اللازم لمعالجة الطلب. تحسينات بعد تنظيم معالجة الرسائل الدفعية

الدرس رقم 6: قبل محاولة إجراء أي تحسينات على النظام ، قم بإعداد الاختبارات التي يمكن الوثوق بنتائجها


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

دعنا نقول بضع كلمات حول الأدوات المحددة المستخدمة لتنظيم الاختبار.

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

توفر الخدمة قيد الاختبار معلومات القياس في Datalog. يتم تقديم هذه المعلومات هنا مع الرسوم البيانية مع خلفية مشرقة.

أعزائي القراء! ما أنظمة اختبار الخدمة Node.js التي تستخدمها؟

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


All Articles