طرق مختلفة لتصحيح الأخطاء في OpenResty

API7.ai

December 16, 2022

OpenResty (NGINX + Lua)

في مجموعة التواصل الخاصة بـ OpenResty، غالبًا ما يطرح المطورون هذا السؤال: كيف يمكن التصحيح في OpenResty؟ على حد علمي، هناك بعض الأدوات في OpenResty التي تدعم تصحيح النقاط الفاصلة، بما في ذلك مكون إضافي في VSCode، ولكنها لم تُستخدم على نطاق واسع حتى الآن. بما في ذلك المؤلف agentzh وبعض المساهمين الذين أعرفهم، الجميع يستخدم أبسط الطرق مثل ngx.log و ngx.say للتصحيح.

هذا ليس ودودًا لمعظم المبتدئين. هل يعني ذلك أن العديد من الحافظين الأساسيين لـ OpenResty لديهم فقط الطريقة البدائية لطباعة السجلات عندما يواجهون مشكلة صعبة؟

بالطبع لا. في عالم OpenResty، SystemTap ورسوم اللهب هي الأدوات القياسية للتعامل مع المشكلات الصعبة ومشكلات الأداء. إذا كان لديك سؤال حول هذا في قائمة بريدية أو مشكلة، سيطلب منك الحافظ المشروع تحميل رسم اللهب وطلب وصف رسومي بدلاً من نصي.

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

نقاط التوقف وطباعة السجلات

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

من هذا المنظور، حل الأخطاء التي تتكرر بشكل ثابت في بيئة الاختبار هو عمل بدني. معظم الأخطاء التي أحلها في عملي تقع في هذه الفئة.

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

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

خوارزمية البحث الثنائي والتعليق

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

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

قد تبدو هذه الطريقة غبية بعض الشيء، ولكنها فعالة في العديد من السيناريوهات. بالطبع، مع تقدم التكنولوجيا وزيادة تعقيد النظام، نوصي باستخدام معيار مثل OpenTracing للتتبع الموزع.

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

أيضًا، إذا كان نظامك أكثر تعقيدًا، مثل في بيئة الخدمات الصغيرة، فإن Zipkin، Apache SkyWalking هي خيارات جيدة.

التصحيح الديناميكي

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

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

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

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

كان Dtrace أحد أول أطر التتبع الديناميكي، وقد أدى تأثيره إلى ظهور أدوات تصحيح ديناميكية مماثلة على أنظمة أخرى. على سبيل المثال، أنشأ مهندسو Red Hat Systemtap على Linux، وهو ما سأتحدث عنه بعد ذلك.

Systemtap

Systemtap لديه DSL الخاص به، والذي يمكن استخدامه لإعداد نقاط التحقيق. قبل أن نخوض في المزيد من التفاصيل، دعنا نثبت Systemtap لتجاوز التجريد. هنا، فقط استخدم مدير الحزم في النظام للتثبيت.

sudo apt install systemtap

لنلق نظرة على برنامج hello world مكتوب بـ Systemtap:

# cat hello-world.stp
probe begin
{
  print("hello world!")
  exit()
}

ألا يبدو ذلك سهلًا؟ تحتاج إلى استخدام صلاحيات sudo لتشغيله.

sudo stap hello-world.stp

سيطبع hello world!. في معظم السيناريوهات، لا نحتاج إلى كتابة نصوص stap الخاصة بنا لإجراء التحليل، لأن OpenResty لديها بالفعل الكثير من نصوص stap الجاهزة لإجراء التحليل المنتظم، وسأقدمها لكم في المقالة القادمة. لذا، اليوم نحتاج إلى فهم موجز لنصوص stap.

بعد بعض الممارسة، نعود إلى مفهومنا، يعمل Systemtap عن طريق تحويل نص stap أعلاه إلى C وتشغيل مترجم C للنظام لإنشاء وحدة kernel. عند تحميل الوحدة، يتم تنشيط جميع أحداث التحقيق عن طريق ربط النواة.

على سبيل المثال، begin سيعمل في بداية التحقيق، و end المقابل، لذا يمكن كتابة برنامج hello world أعلاه بالطريقة التالية:

probe begin
{
  print("hello ")
  exit()
}

probe end
{
print("world!")

هنا، قدمت فقط مقدمة سريعة جدًا لـ Systemtap. كتب Frank Ch. Eigler، مؤلف Systemtap، كتابًا إلكترونيًا Systemtap tutorial الذي يقدم Systemtap بالتفصيل. إذا كنت ترغب في التعلم أكثر وفهم Systemtap بعمق، أقترح البدء بهذا الكتاب كأفضل مسار تعليمي.

أطر التتبع الديناميكي الأخرى

Systemtap ليس كافيًا لمهندسي النواة وتحليل الأداء.

  1. Systemtap لا يدخل نواة النظام بشكل افتراضي.
  2. يعمل بطريقة تجعل التمهيد بطيئًا وقد يكون له تأثير على التشغيل الطبيعي للنظام.

eBPF (BPF الموسع) هي ميزة جديدة تمت إضافتها إلى نواة Linux في السنوات الأخيرة. مقارنة بـ Systemtap، يتمتع eBPF بمزايا الدعم المباشر للنواة، عدم التسبب في تعطل النظام، والتمهيد السريع. في الوقت نفسه، لا يستخدم DSL، بل يستخدم بناء جملة C مباشرة، لذا فهو أسهل بكثير في البدء.

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

رسم اللهب

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

رسم اللهب

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

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

الخلاصة

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

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