
تضمين التغريدة
اليوم سوف نتحدث عن سجلات الأحداث ، والمقاييس الكمية ، ومراقبة كل هذا من أجل زيادة معدل استجابة الفريق للحوادث وتقليل وقت توقف النظام المستهدف.
إرلانج / مكتب المدعي العام كإطار وأيديولوجية بناء النظم الموزعة يعطينا مقاربات منظمة لتطوير والأدوات وتنفيذ المكونات القياسية. دعنا نقول أننا استخدمنا إمكانات OTP وانتقلنا من النموذج الأولي إلى الإنتاج. يشعر مشروع Erlang بشعور رائع على خوادم المعارك ، وقاعدة الكود تتطور باستمرار ، وتظهر متطلبات ووظائف جديدة ، ويأتي أشخاص جدد إلى الفريق ، ويبدو أن كل شيء على ما يرام. لكن في بعض الأحيان يحدث خطأ ما ، وقد تؤدي المشكلات التقنية ، مضروبة بالعامل البشري ، إلى وقوع حادث.
نظرًا لأنه من المستحيل وضع قش لجميع حالات الفشل والمشاكل المحتملة تمامًا ، أو أنها ليست مجدية اقتصاديًا ، فمن الضروري تقليل وقت تعطل النظام في حالة حدوث فشل من جانب حلول الإدارة والبرامج.
في نظم المعلومات ، سيكون هناك دائمًا احتمال حدوث حالات فشل ذات طبيعة مختلفة:
- فشل الأجهزة وفشل الطاقة
- فشل الشبكة: أخطاء التكوين ، منحنيات البرامج الثابتة
- الأخطاء المنطقية: من أخطاء تشفير الخوارزمية إلى المشكلات المعمارية التي تنشأ عند حدود الأنظمة والأنظمة الفرعية.
- القضايا الأمنية والهجمات ذات الصلة والخارقة ، بما في ذلك الاحتيال الداخلي.
على الفور نميز المسؤولية: مراقبة البنية التحتية ، على سبيل المثال ، التي تنظمها zabbix ، ستكون مسؤولة عن تشغيل معدات الحوسبة وشبكات نقل البيانات. لقد كتب الكثير عن تثبيت هذا الرصد وتكوينه ، ولن نكرره.
من وجهة نظر المطور ، تكمن مشكلة إمكانية الوصول والجودة في مستوى الاكتشاف المبكر للأخطاء ومشاكل الأداء والاستجابة السريعة لها. وهذا يتطلب نهج ووسائل التقييم. لذلك ، دعونا نحاول استنباط مقاييس كمية ، وتحليل أي مراحل مختلفة من تطوير وتشغيل المشروع ، يمكننا تحسين الجودة بشكل كبير.
أنظمة التجميع
اسمحوا لي أن أذكرك مرة أخرى بأهمية النهج الهندسي والاختبار في تطوير البرمجيات. يقدم Erlang / OTP إطارين للاختبار في وقت واحد: eunit و test test.
كمقاييس للتقييم الأولي لحالة قاعدة الشفرة ودينامياتها ، يمكنك استخدام عدد الاختبارات الناجحة والمشاكل ، ووقت تنفيذها ، والنسبة المئوية لتغطية الشفرة مع الاختبارات. كلا الإطارين يسمحان بحفظ نتائج الاختبار بتنسيق Junit.
على سبيل المثال ، بالنسبة إلى rebar3 و ct ، أضف الأسطر التالية إلى rebar.config:
{cover_enabled, true}. {cover_export_enabled, true}. {ct_opts,[ {ct_hooks, [{cth_surefire, [{path, "report.xml"}]}]} ]}.
سيسمح لك عدد الاختبارات الناجحة وغير الناجحة بإنشاء مخطط اتجاهي:

بالنظر إلى ذلك ، يمكنك تقييم ديناميات الفريق وانحدار الاختبارات. على سبيل المثال ، في جنكينز ، يمكن الحصول على هذا الرسم البياني باستخدام البرنامج المساعد لاختبار نتائج الاختبار.
إذا تحولت الاختبارات إلى اللون الأحمر أو بدأت في التشغيل لفترة طويلة ، فستسمح المقاييس بوضع اللمسات الأخيرة على الإصدار حتى في مرحلة التجميع والاختبار التلقائي.
مقاييس التطبيق
بالإضافة إلى مقاييس نظام التشغيل ، يجب أن تتضمن المراقبة مقاييس التطبيق ، مثل عدد مرات المشاهدة في الثانية ، وعدد المدفوعات ، والمؤشرات الهامة الأخرى.
في ${application}.${metrics_type}.${name}
، أستخدم قالبًا مثل ${application}.${metrics_type}.${name}
لتسمية المقاييس. تسمح لك هذه التسمية بالحصول على قوائم مقاييس النموذج
messaging.systime_subs.messages.delivered = 1654 messaging.systime_subs.messages.proxied = 0 messaging.systime_subs.messages.published = 1655 messaging.systime_subs.messages.skipped = 3
ربما كلما زاد عدد المقاييس ، كلما كان فهم ما يحدث في نظام معقد أسهل.
إرلانج VM المقاييس
يجب إيلاء اهتمام خاص لمراقبة Erlang VM. إن أيديولوجية السماح لها بالتعطل جميلة ، وسيساعد الاستخدام المناسب لـ OTP بالتأكيد على رفع الأجزاء الساقطة من التطبيق داخل Erlang VM. ولكن لا تنسى أن Erlang VM نفسه ، لأنه من الصعب إسقاطه ، لكن ذلك ممكن. تستند جميع الخيارات إلى استنفاد الموارد. نحن قائمة أهمها:
جدول ذرة الفائض.
الذرات هي معرفات هدفها الأساسي هو تحسين قابلية قراءة الكود. تبقى الذرات التي تم إنشاؤها مرة واحدة إلى الأبد في ذاكرة مثيل Erlang VM ، حيث لا يتم إزالتها من قبل جامع البيانات المهملة. لماذا يحدث هذا؟ يعمل مجمّع البيانات المهملة بشكل منفصل في كل عملية مع بيانات من هذه العملية ، بينما يمكن توزيع الذرات عبر هياكل البيانات للعديد من العمليات.
افتراضيًا ، يمكن إنشاء 1،048،576 ذرة. في مقالات حول قتل Erlang VM ، يمكنك عادة العثور على شيء مثل هذا.
[list_to_atom(integer_to_list(I)) || I <- lists:seq(erlang:system_info(atom_count), erlang:system_info(atom_limit))]
كتوضيح لهذا التأثير. يبدو أنه لا يمكن الوصول إلى مشكلة مصطنعة في الأنظمة الحقيقية ، ولكن هناك حالات ... على سبيل المثال ، في معالج واجهة برمجة التطبيقات الخارجية ، عند تحليل الطلبات ، binary_to_atom/2
binary_to_existing_atom/2
بدلاً من binary_to_existing_atom/2
أو list_to_atom/1
بدلاً من list_to_existing_atom/1
.
يجب استخدام المعلمات التالية لمراقبة حالة الذرات:
erlang:memory(atom_used)
- مقدار الذاكرة المستخدمة للذراتerlang:system_info(atom_count)
- عدد الذرات التي تم إنشاؤها في النظام. جنبا إلى جنب مع erlang:system_info(atom_limit)
، يمكن حساب استخدام الذرة.
تسريبات العملية.
أود أن أقول على الفور أنه عندما يتم الوصول إلى process_limit (+ P ، فإن erl) لا تسقط حجة erlang vm ، لكنها تذهب إلى حالة الطوارئ ، على سبيل المثال ، سيكون من المستحيل الاتصال بها. في النهاية ، سوف يؤدي نفاد الذاكرة المتوفرة عند تخصيص العمليات المسربة إلى تعطل erlang vm.
erlang:system_info(process_count)
- عدد العمليات النشطة في الوقت الحالي. جنبا إلى جنب مع erlang:system_info(process_limit)
، يمكن حساب استخدام العملية.erlang:memory(processes)
- الذاكرة المخصصة للعملياتerlang:memory(processes_used)
- الذاكرة المستخدمة للعمليات.
تجاوز عملية صندوق البريد.
مثال نموذجي على مثل هذه المشكلة هو أن عملية المرسل ترسل رسائل إلى عملية المستلم دون انتظار التأكيد ، بينما receive
في عملية المستلم كل هذه الرسائل بسبب نمط مفقود أو غير صحيح. نتيجة لذلك ، يتم تجميع الرسائل في صندوق البريد. على الرغم من أن erlang لديه آلية لإبطاء المرسل في حالة عدم تمكن المعالج من معالجة المعالجة ، على أي حال ، بعد استنفاذ الذاكرة المتوفرة ، يتعطل vm.
لفهم ما إذا كانت هناك مشاكل في تجاوز سعة صندوق البريد ، سوف يساعد etop.
$ erl -name etop@host -hidden -s etop -s erlang halt -output text -node dest@host -setcookie some_cookie -tracing off -sort msg_q -interval 1 -lines 25

كمقياس للرصد المستمر ، يمكنك أن تأخذ عدد عمليات المشكلة. للتعرف عليهم ، يمكنك استخدام الوظيفة التالية:
top_msq_q()-> [{P, RN, L, IC, ST} || P <- processes(), { _, L } <- [ process_info(P, message_queue_len) ], L >= 1000, [{_, RN}, {_, IC}, {_, ST}] <- [process_info(P, [registered_name, initial_call, current_stacktrace]) ] ].
أيضا ، يمكن تسجيل هذه القائمة ، ثم عند تلقي إخطار من المراقبة ، يتم تبسيط تحليل المشكلة.
تسرب الثنائيات.
يتم تخصيص ذاكرة للثنائيات الكبيرة (أكثر من 64 بايت) في كومة الذاكرة المؤقتة العامة. تحتوي الكتلة المخصصة على عداد مرجعي يوضح عدد العمليات التي لها حق الوصول إليها. بعد إعادة ضبط العداد ، يحدث التنظيف. أبسط نظام ، ولكن ، كما يقولون ، هناك فروق دقيقة. من حيث المبدأ ، هناك إمكانية لتوليد الكثير من البيانات المهملة على الكومة بحيث لا يحتوي النظام على ذاكرة كافية لإجراء عملية التنظيف.
erlang:memory(binary)
كمقياس للمراقبة ، تُظهر الذاكرة المخصصة للثنائيات.
لذلك ، يتم فرز الحالات التي تؤدي إلى سقوط vm ، ومع ذلك ، من الجيد أن تراقب ما لا يقل أهمية عن المعاملات التي تؤثر بشكل مباشر أو غير مباشر على الأداء الصحيح للتطبيقات الخاصة بك:
- الذاكرة المستخدمة من قبل ETS:
erlang:memory(ets)
. - ذاكرة الوحدات النمطية المترجمة:
erlang:memory(code)
.
إذا لم تستخدم الحلول الخاصة بك ترجمة برمجية ديناميكية ، فيمكن استبعاد هذا الخيار.
وأود أيضا أن أذكر erlydtl. إذا قمت بترجمة القوالب بشكل حيوي ، فإن التحويل البرمجي ينشئ حزمة يتم تحميلها في ذاكرة vm. يمكن أن يسبب أيضا تسرب الذاكرة. - ذاكرة النظام:
erlang:memory(system)
. يظهر استهلاك الذاكرة وقت التشغيل erlang. - إجمالي الذاكرة المستهلكة:
erlang:memory(total)
. هذا هو مقدار الذاكرة التي تستهلكها العمليات ووقت التشغيل. - معلومات حول التخفيضات:
erlang:statistics(reductions)
. - عدد العمليات والمنافذ الجاهزة للتنفيذ:
erlang:statistics(run_queue)
. - يتيح لك
erlang:statistics(runtime)
مثيل vm: erlang:statistics(runtime)
فهم ما إذا كان هناك إعادة تشغيل دون تحليل السجل. - نشاط الشبكة:
erlang:statistics(io)
.
تقديم المقاييس إلى zabbix
سنقوم بإنشاء ملف يحتوي على مقاييس التطبيق ومقاييس erlang vm ، والتي سنقوم بتحديثها كل N ثانية. لكل عقدة erlang ، يجب أن يحتوي ملف القياس على مقاييس التطبيقات التي تعمل عليه ومقاييس مثيل erlang vm. يجب أن تكون النتيجة شيء مثل هذا:
messaging.systime_subs.messages.delivered = 1654 messaging.systime_subs.messages.proxied = 0 messaging.systime_subs.messages.published = 1655 messaging.systime_subs.messages.skipped = 3 …. erlang.io.input = 2205723664 erlang.io.output = 1665529234 erlang.memory.binary = 1911136 erlang.memory.ets = 1642416 erlang.memory.processes = 23596432 erlang.memory.processes_used = 23598864 erlang.memory.system = 50883752 erlang.memory.total = 74446048 erlang.processes.count = 402 erlang.processes.run_queue = 0 erlang.reductions = 148412771 ....
باستخدام zabbix_sender
سنرسل هذا الملف إلى zabbix ، حيث يتوفر بالفعل تمثيل رسومي والقدرة على إنشاء مشغلات للأتمتة والإعلام.
الآن بعد أن أصبح لدينا مقاييس في نظام المراقبة ومشغلات الأتمتة وأحداث الإشعارات التي تم إنشاؤها على أساسها ، لدينا فرصة لتجنب الحوادث من خلال الرد مسبقًا على جميع الانحرافات الخطيرة من حالة وظيفية بالكامل.
التجمع المركزي للسجلات
عندما يكون هناك 1-2 خوادم في مشروع ، ربما لا يزال بإمكانك العيش بدون مجموعة سجلات مركزية ، ولكن بمجرد ظهور نظام موزع مع العديد من الخوادم والمجموعات والبيئات ، يصبح من الضروري حل مشكلة تجميع السجلات وعرضها بطريقة مريحة.
لكتابة السجلات في المشاريع الخاصة بي ، أستخدم الجعة. غالبًا ، في الطريق من النموذج الأولي إلى الإنتاج ، تمر المشاريع بالمراحل التالية من جمع السجلات:
- أبسط تسجيل مع الإخراج إلى ملف محلي أو حتى stdout (lager_file_backend)
- مجموعة مركزية من السجلات باستخدام ، على سبيل المثال ، syslogd والإرسال التلقائي للسجلات إلى المجمع. لمثل هذا المخطط ، lager_syslog مناسب.
العيب الرئيسي للنظام هو أنك بحاجة إلى الانتقال إلى خادم تجميع السجلات ، والعثور على الملف بالسجلات اللازمة وتصفية الأحداث بطريقة ما بحثًا عن الأحداث اللازمة لتصحيح الأخطاء. - مجموعة سجلات مركزية مع تخزين في المستودع مع إمكانية تصفية السجلات والبحث فيها.
حول السلبيات والإيجابيات والمقاييس الكمية التي يمكن تطبيقها باستخدام الأخير ، وسوف نتحدث في منظور تنفيذ محدد - lager_clickhouse
، والذي أستخدمه في معظم المشاريع المتقدمة. بضع كلمات عن lager_clickhouse
. هذا هو الخلفية الجعة لحفظ الأحداث إلى clickhouse. في الوقت الحالي ، هذا مشروع داخلي ، ولكن هناك خطط لجعله مفتوحًا. عند تطوير lager_clickhouse ، اضطررت إلى تجاوز بعض ميزات clickhouse ، على سبيل المثال ، استخدم التخزين المؤقت للأحداث لتجنب تقديم طلبات متكررة في clickhouse. الجهد المبذول آتى ثماره مع التشغيل المستقر والأداء الجيد.
يتمثل الطرح الرئيسي لطريقة الحفظ في المستودع في كليك كليكرة إضافية والحاجة إلى تطوير كود لحفظ الأحداث فيه وواجهة المستخدم لتحليل الأحداث والبحث عنها. أيضًا ، بالنسبة لبعض المشروعات ، قد يكون من الضروري استخدام tcp لإرسال السجلات.
لكن إيجابيات ، كما يبدو لي ، تفوق كل العيوب المحتملة.
بحث سهل وسريع عن الحدث:
- تصفية حسب التاريخ دون الحاجة إلى البحث عن ملف / ملفات على خادم مركزي يحتوي على مجموعة من الأحداث.
- تصفية حسب البيئة. تتم كتابة السجلات من أنظمة فرعية مختلفة وغالبًا من مجموعات مختلفة إلى مستودع واحد. في الوقت الحالي ، يحدث الفصل وفقًا للتسميات التي تم تعيينها على كل عقدة من الكتلة.
- تصفية حسب اسم المضيف
- تصفية حسب اسم الوحدة النمطية التي أرسلت الحدث
- تصفية الأحداث
- البحث عن النص
يظهر عرض مثال لواجهة عرض السجل في لقطة الشاشة:

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