ضبط أداء المعاملات التجارية الموزعة

Azure Kubernetes Service (AKS)
Azure Cache for Redis

توضح هذه المقالة كيف استخدم فريق التطوير القياسات للعثور على الازدحام وتحسين أداء النظام الموزَّع. تستند المقالة إلى اختبار التحميل الفعلي الذي أجريناه على تطبيق نموذجي. التطبيق من أساس خدمة Azure Kubernetes (AKS) للخدمات المصغرة.

هذه المقالة جزء من سلسلة. اقرأ الجزء الأول هنا.

السيناريو: يبدأ تطبيق العميل معاملة تجارية تتضمن خطوات متعددة.

يتضمن هذا السيناريو تطبيق تسليم الطائرات بدون طيار الذي يعمل على AKS. يستخدم العملاء تطبيق ويب لجدولة عمليات التسليم عن طريق الطائرات بدون طيار. تتطلب كل معاملة خطوات متعددة يتم تنفيذها بواسطة خدمات مصغرة منفصلة على النهاية الخلفية:

  • تدير خدمة التسليم عمليات التسليم.
  • تحدد خدمة مجدول الطائرات بدون طيار جداول لطائرات بدون طيار للاستلام.
  • تدير خدمة الحزمة الحزم.

هناك خدمتان أخريان: خدمة العرض التي تقبل طلبات العميل وتضعها في قائمة انتظار للمعالجة، وخدمة سير العمل التي تنسق الخطوات في سير العمل.

رسم تخطيطي يوضح سير العمل الموزع

لمزيد من المعلومات حول هذا السيناريو، راجع تصميم بنية الخدمات المصغرة.

اختبار 1: خط الأساس

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

الإعداد القيمة
عقد المجموعة 6
Pods 3 لكل خدمة

يعرض الرسم البياني التالي نتائج اختبار التحميل، كما هو موضح في Visual Studio. يرسم الخط الأرجواني تحميل المستخدم، ويرسم الخط البرتقالي إجمالي الطلبات.

رسم بياني لنتائج اختبار تحميل Visual Studio

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

ما نريد حقاً أن نعرفه هو ما إذا كانت الخلفية تواكب معدل الطلب. يمكن أن تستوعب قائمة انتظار ناقل خدمة Microsoft Azure زيادة الطلب، ولكن إذا لم تتمكن الواجهة الخلفية من التعامل مع الحمل المستمر، فستنخفض المعالجة أكثر فأكثر.

فيما يلي رسم بياني أكثر إفادة. يقوم برسم عدد الرسائل الواردة والصادرة في قائمة انتظار ناقل خدمة Microsoft Azure. يتم عرض الرسائل الواردة باللون الأزرق الفاتح، وتظهر الرسائل الصادرة باللون الأزرق الداكن:

رسم بياني للرسائل الواردة والصادرة

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

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

بالتأكيد بما فيه الكفاية، تظهر خريطة التطبيق أن خدمة Workflow تتلقى أخطاء من خدمة التسليم:

لقطة شاشة لخريطة التطبيق

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

لقطة شاشة لعرض المعاملة من طرف إلى طرف

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

الاختبار 2: زيادة حجم ذاكرة التخزين المؤقت

بالنسبة لاختبار التحميل الثاني، زاد فريق التطوير حجم ذاكرة التخزين المؤقت في Azure Cache ل Redis. (راجع كيفية تغيير حجم ذاكرة Azure Cache ل Redis.) حل هذا التغيير استثناءات نفاد الذاكرة، والآن تظهر خريطة التطبيق صفر أخطاء:

لقطة شاشة ل Application Map توضح أن زيادة حجم ذاكرة التخزين المؤقت حلت استثناءات نفاد الذاكرة.

ومع ذلك، لا يزال هناك تأخير كبير في معالجة الرسائل. في ذروة اختبار التحميل، يكون معدل الرسالة الواردة أكثر من 5 أضعاف معدل الصادر:

الرسم البياني للرسائل الواردة والصادرة التي تظهر معدل الرسائل الواردة هو أكثر من 5 أضعاف معدل الصادر.

يقيس الرسم البياني التالي معدل النقل من حيث إكمال الرسالة — أي المعدل الذي تحدد به خدمة Workflow رسائل ناقل خدمة Microsoft Azure كمكتملة. تمثل كل نقطة في الرسم البياني 5 ثوانٍ من البيانات، وتعرض ~16/sec الحد الأقصى لمعدل النقل.

رسم بياني لمعدل نقل الرسالة

تم إنشاء هذا الرسم البياني عن طريق تشغيل استعلام في مساحة عمل Log Analytics، باستخدام لغة استعلام Kusto:

let start=datetime("2020-07-31T22:30:00.000Z");
let end=datetime("2020-07-31T22:45:00.000Z");
dependencies
| where cloud_RoleName == 'fabrikam-workflow'
| where timestamp > start and timestamp < end
| where type == 'Azure Service Bus'
| where target has 'https://dev-i-iuosnlbwkzkau.servicebus.windows.net'
| where client_Type == "PC"
| where name == "Complete"
| summarize succeeded=sumif(itemCount, success == true), failed=sumif(itemCount, success == false) by bin(timestamp, 5s)
| render timechart

الاختبار 3: توسيع نطاق خدمات الواجهة الخلفية

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

الإعداد القيمة
عقد المجموعة 6
خدمة الاستيعاب 3 نسخ متماثلة
خدمة سير العمل 3 نسخ متماثلة
خدمات الحزمة والتسليم وجدولة الطائرات بدون طيار 6 نسخ متماثلة لكل منها

لسوء الحظ، يظهر اختبار التحميل هذا تحسناً متواضعاً فقط. لا تزال الرسائل الصادرة لا تواكب الرسائل الواردة:

رسم بياني للرسائل الواردة والصادرة يوضح أن الرسائل الصادرة لا تزال لا تواكب الرسائل الواردة.

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

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

علاوة على ذلك، بالنظر إلى رؤى حاوية Azure Monitor، يبدو أن المشكلة لا تحدث بسبب استنفاد الموارد داخل نظام المجموعة. أولاً، تظهر مقاييس مستوى العقدة أن استخدام وحدة المعالجة المركزية لا يزال أقل من 40% حتى عند النسبة المئوية 95، واستخدام الذاكرة حوالي 20%.

رسم بياني لاستخدام عقدة AKS

في بيئة Kubernetes، من الممكن أن تكون الجرابات الفردية مقيدة بالموارد حتى عندما لا تكون العقد مقيدة. ولكن طريقة العرض على مستوى الجراب تظهر أن جميع الجرابات سليمة.

رسم بياني لاستخدام جراب AKS

من هذا الاختبار، يبدو أن مجرد إضافة المزيد من الجرابات إلى النهاية الخلفية لن يساعد. الخطوة التالية هي البحث عن كثب في خدمة سير العمل لفهم ما يحدث عند معالجة الرسائل. يظهر Application Insights أن متوسط مدة عملية خدمة Process سير العمل هو 246 مللي ثانية.

لقطة شاشة ل Application Insights

يمكننا أيضاً تشغيل استعلام للحصول على مقاييس على العمليات الفردية داخل كل معاملة:

الهدف percentile_duration_50 percentile_duration_95
https://dev-i-iuosnlbwkzkau.servicebus.windows.net/ | dev-i-iuosnlbwkzkau 86.66950203 283.4255578
التوصيل 37 57
package 12 17
مجدول الطائرات بدون طيار 21 41

يمثل الصف الأول في هذا الجدول قائمة انتظار ناقل خدمة Microsoft Azure. الصفوف الأخرى هي المكالمات إلى خدمات الواجهة الخلفية. للرجوع إليها، إليك استعلام Log Analytics لهذا الجدول:

let start=datetime("2020-07-31T22:30:00.000Z");
let end=datetime("2020-07-31T22:45:00.000Z");
let dataset=dependencies
| where timestamp > start and timestamp < end
| where (cloud_RoleName == 'fabrikam-workflow')
| where name == 'Complete' or target in ('package', 'delivery', 'dronescheduler');
dataset
| summarize percentiles(duration, 50, 95) by target

لقطة شاشة لنتيجة استعلام Log Analytics

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

يجب أن يكون ذلك ممكناً في هذا السيناريو، لسببين:

  • هذه هي مكالمات الشبكة، لذلك يتم قضاء معظم الوقت في انتظار اكتمال الإدخال/الإخراج
  • الرسائل مستقلة، ولا تحتاج إلى معالجتها بالترتيب.

الاختبار 4: زيادة التوازي

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

الإعداد الوصف افتراضي القيمة الجديدة
MaxConcurrentCalls الحد الأقصى لعدد الرسائل التي يجب معالجتها بشكل متزامن. 1 20
PrefetchCount كم عدد الرسائل التي سيجلبها العميل مسبقاً إلى ذاكرة التخزين المؤقت المحلية الخاصة به. 0 3000

لمزيد من المعلومات، راجع أفضل الممارسات لتحسين الأداء باستخدام ناقل خدمة Microsoft Azure Messaging . يؤدي تشغيل الاختبار باستخدام هذه الإعدادات إلى إنتاج الرسم البياني التالي:

رسم بياني للرسائل الواردة والصادرة يعرض عدد الرسائل الصادرة التي تتجاوز بالفعل العدد الإجمالي للرسائل الواردة.

يتم عرض الرسائل الواردة باللون الأزرق الفاتح، وتظهر الرسائل الصادرة باللون الأزرق الداكن.

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

يمكن العثور على دليل على هذا اللغز في طريقة عرض التبعيات في Application Insights. يلخص هذا المخطط جميع الاستدعاءات التي قامت بها خدمة سير العمل إلى ناقل خدمة Microsoft Azure:

رسم بياني لمكالمات التبعية

لاحظ إدخال DeadLetter. تشير هذه المكالمات إلى أن الرسائل تنتقل إلى قائمة انتظار الرسائل غير المستخدمة لناقل خدمة Microsoft Azure.

لفهم ما يحدث، تحتاج إلى فهم دلالات Peek-Lock في ناقل خدمة Microsoft Azure. عندما يستخدم العميل Peek-Lock، يقوم ناقل خدمة Microsoft Azure باسترداد رسالة وتأمينها تلقائياً. أثناء الاحتفاظ بالقفل، يضمن عدم تسليم الرسالة إلى أجهزة استقبال أخرى. في هذا الوضع، عند انتهاء صلاحية التأمين، تصبح الرسالة متاحة للمستلمين الآخرين. بعد الحد الأقصى لعدد محاولات التسليم (وهو قابل للتكوين)، سيضع ناقل خدمة Microsoft Azure الرسائل في قائمة انتظار غير مستخدمة، حيث يمكن فحصها لاحقاً.

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

يمكنك أيضاً مشاهدة هذا السلوك في الاستثناءات، حيث يتم تسجيل استثناءات عديدة MessageLostLockException:

لقطة شاشة لاستثناءات Application Insights تعرض العديد من استثناءات MessageLostLockException.

الاختبار 5: زيادة مدة التأمين

بالنسبة لاختبار التحميل هذا، تم تعيين مدة تأمين الرسالة إلى 5 دقائق، لمنع مهلات التأمين. يوضح الرسم البياني للرسائل الواردة والصادرة الآن أن النظام يواكب معدل الرسائل الواردة:

رسم بياني للرسائل الواردة والصادرة يوضح أن النظام يواكب معدل الرسائل الواردة.

على مدى المدة الإجمالية لاختبار التحميل لمدة 8 دقائق، أكمل التطبيق 25 ألف عملية، مع ذروة معدل نقل تبلغ 72 عملية/ثانية، ما يمثل زيادة بنسبة 400% في الحد الأقصى لمعدل النقل.

رسم بياني لمعدل نقل الرسائل يظهر زيادة بنسبة 400٪ في الحد الأقصى لمعدل النقل.

ومع ذلك، أظهر تشغيل نفس الاختبار لمدة أطول أن التطبيق لا يمكنه الحفاظ على هذا المعدل:

رسم بياني للرسائل الواردة والصادرة يوضح أن التطبيق لا يمكنه الحفاظ على هذا المعدل.

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

رسم بياني لاستخدام عقدة AKS يوضح أن الحد الأقصى لاستخدام وحدة المعالجة المركزية كان قريبا من 100٪.

الاختبار 6: توسيع نطاق خدمات الواجهة الخلفية (مرة أخرى)

لاختبار التحميل النهائي في السلسلة، تحجيم الفريق لمجموعة Kubernetes والجرابات على النحو التالي:

الإعداد القيمة
عقد المجموعة 12
خدمة الاستيعاب 3 نسخ متماثلة
خدمة سير العمل 6 نسخ متماثلة
خدمات الحزمة والتسليم وجدولة الطائرات بدون طيار 9 نسخ متماثلة لكل منها

أدى هذا الاختبار إلى زيادة معدل النقل المستمر، مع عدم وجود تأخر كبير في معالجة الرسائل. وعلاوة على ذلك، ظل استخدام وحدة المعالجة المركزية للعقدة أقل من 80%.

رسم بياني لمعدل نقل الرسائل يظهر معدل نقل مستداما أعلى، مع عدم وجود تأخر كبير في معالجة الرسائل.

الملخص

بالنسبة لهذا السيناريو، تم تحديد الازدحام التالية:

  • استثناءات نفاد الذاكرة في Azure Cache ل Redis.
  • عدم وجود توازي في معالجة الرسائل.
  • مدة تأمين الرسائل غير كافية، مما يؤدي إلى وضع مهلات التأمين والرسائل في قائمة انتظار الرسائل غير المستخدمة.
  • استنفاد وحدة المعالجة المركزية.

لتشخيص هذه المشكلات، اعتمد فريق التطوير على القياسات التالية:

  • معدل رسائل ناقل خدمة Microsoft Azure الواردة والصادرة.
  • مخطط Application في Application Insights.
  • الأخطاء والاستثناءات.
  • استعلامات تحليلات السجل المخصصة.
  • استخدام وحدة المعالجة المركزية والذاكرة في نتائج تحليلات حاوية Azure Monitor.

الخطوات التالية

لمزيد من المعلومات حول هذا السيناريو، راجع تصميم بنية الخدمات المصغرة.