في اليوم الآخر ، عُقد Moscow Python Meetup # 66 - يواصل المجتمع مناقشة الأدوات ذات الصلة التي تعزز اللغة وتكييفها مع بيئات مختلفة. بما في ذلك في الاجتماع ، تم تقديم تقريري. اسمي مسمار ، وأنا أفعل Yandex.Connect.

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

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

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

أي نوع من المقاييس يمكن أن نأخذها؟ سأركز على تطوير تطبيقات الويب ، لأنها أقرب إلي. على سبيل المثال ، يمكننا تصوير عدد الطلبات ونقاط النهاية لدينا ووقت استجابة نقاط النهاية لدينا ورموز الاستجابة للخدمات ذات الصلة ، إذا ذهبنا إليها ولدينا بنية microservice. إذا استخدمنا ذاكرة التخزين المؤقت ، فيمكننا أن نفهم مدى فعالية ذاكرة التخزين المؤقت المفقودة أو نتائج البحث ، وفهم توزيع أوقات الاستجابة لكل من خوادم الجهة الخارجية ، وعلى سبيل المثال ، قاعدة البيانات. ولكن لكي ترى المقاييس ، تحتاج إلى جمعها بطريقة أو بأخرى.

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

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

خيار آخر هو السجلات. نكتب جميع السجلات ونرسلها إلى مكان ما. لا شيء يمنعنا من أخذ هذه السجلات ، ومعالجتها بطريقة ما والحصول على مقاييس تستند إلى السجلات.
على سبيل المثال ، نكتب حقيقة طلب المستخدم في السجل ، ثم نأخذ سجلات ، hop-hop ، محسوبة. مثال نموذجي هو ELK (Elasticsearch ، Logstash ، Kibana).

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

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

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

إذا حفظنا محليًا ، كقاعدة عامة ، فهذا مناسب للحالة بعملية واحدة. ونحن ، في uWSGI لدينا ، ندير عدة عمليات على التوازي. أو يمكننا استخدام نوع من التخزين المشترك. ما الذي يتبادر إلى أذهاننا كلمة "التخزين المشترك"؟ هذا نوع من قواعد بيانات Redis أو Memcached أو العلائقية أو غير العلائقية ، أو حتى ملف.

حول uWSGI. دعني أذكرك بأولئك الذين يستخدمونها قليلًا أو نادرًا: uWSGI هو خادم ويب للتطبيقات يتيح لك تشغيل تطبيقات Python تحتك. ينفذ الواجهة ، بروتوكول uWSGI. يوصف هذا البروتوكول في PEP 333 ، المهتمين ، يمكنك القراءة.

سوف يساعدنا أيضًا في اختيار أفضل حل Yandex.Tank. هذه أداة لاختبار التحميل ، تتيح لك إمكانية قصف تطبيقنا بملفات تعريف تحميل متنوعة وإنشاء رسومات جميلة. أو أنه يعمل في وحدة التحكم ، كما تريد.

التجارب. سننشئ تطبيقًا اصطناعيًا لاختباراتنا الاصطناعية ، وسنقوم بتطبيقه باستخدام دبابة. سيكون لتطبيق uWSGI صراع بسيط مع 10 عمال.

هنا هو التطبيق لدينا قارورة. الحمولة الصافية التي ينفذها تطبيقنا ، سنحاكي حلقة فارغة.

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

أبسط خيار هو استخدام PostgreSQL. لأننا نعمل مع بوستجرس ، لدينا ذلك. دعونا نستخدم ما هو جاهز بالفعل.
دعنا نقول لدينا تسمية في PostgreSQL التي ببساطة زيادة العداد.

بالفعل على كميات صغيرة من RPS نرى تدهور قوي في الأداء. يمكن القول ضخمة فقط.

الخيار التالي هو Redis. لكننا هنا نقوم بذكاء أكبر: نقوم بتثبيته محليًا والذهاب إليه ليس عبر الشبكة ، ولكن من خلال مقبس Unix. أيضا زيادة العداد.

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

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

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

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

ذاكرة التخزين المؤقت للنظام الفرعي هي ذاكرة التخزين المؤقت المضمنة في uWSGI. وحدة سريعة وآمنة للخيوط ، وهي تخزين عادي ذو قيمة أساسية.

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

مرة أخرى ، الخيار هو تطبيق يستخدم مربع uWSGI.

هنا نتائج قصف هذا التطبيق.

النتيجة بدون مقاييس ، إذا كانت مع uWSGI ، بالامتداد ، فإنها تبدو كما هي تقريبًا.

كما ترون ، في حالة uWSGI ، نفقد 5٪ فقط من الأداء بالنسبة إلى إصدار "الفانيليا" بدون مقاييس. الخيارات الأخرى لها تراجع كبير إلى حد ما ، وبالتالي ، نتيجة تصويت المتفرج ، يفوز uWSGI.

كيف نطبق هذا؟ كتبنا مكتبة صغيرة ، غلاف حول uWSGI. على سبيل المثال ، نقوم بتثبيت مثيل لمكتبتنا وهنا نضيف "وقت استعلام قاعدة البيانات" المتري كمثال.

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

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

نتيجة لذلك ، نحصل على رسم بياني ، وهو في هذه الحالة المئوية التاسعة والتسعين من وقت وصول ذاكرة التخزين المؤقت والقراءة والكتابة.

أو ، كخيار ، عدد طلبات خدمة الجهات الخارجية إلى واجهة برمجة التطبيقات لدينا.

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

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

لقد رفضنا التخليل ، ونقلنا إلى cashe inc ، وقياس كل شيء ، أصبح أسرع.

في التطبيق الجديد ، نقضي معظم وقتنا في العمل مع ذاكرة التخزين المؤقت ، وليس التخليل.

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