اختبار الأداء والتحميل

تحليل النتائج وإعداد التقارير

18 دقيقة الدرس 9 من 28

تحليل النتائج وإعداد التقارير

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

قراءة منحنيات الشريحة المئوية

يرسم منحنى زمن الاستجابة للشريحة المئوية (المعروف بـ "CDF للاستجابة" أو "منحنى زمن الاستجابة مقابل الحمل") مقياس pXX للاستجابة مقارنةً بالحمل المُقدَّم المتزايد (طلبات في الثانية أو التزامن). شكل المنحنى يخبرك بأكثر بكثير مما يخبرك به رقم واحد.

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

Percentile latency curves showing saturation point and capacity headroom Latency (ms) Offered Load (RPS) 0 50 100 200 400 800 0 200 400 600 800 1000 Saturation ~630 RPS Current ~400 RPS p50 p95 p99 Headroom Zone Saturation Zone
منحنيات استجابة الشريحة المئوية: يبقى p50 ثابتاً، بينما ينحرف p99 أولاً عند نقطة التشبع. تمثل المنطقة الخضراء هامش التشغيل الآمن.

الملاحظات الرئيسية من شكل هذه المنحنيات:

  • المنطقة المسطحة (منطقة الهامش): جميع الشرائح المئوية ثابتة ومتقاربة. النظام لديه طاقة احتياطية؛ إضافة حمل لا تزيد زمن الاستجابة بشكل ملحوظ. هنا يجب أن تعمل في الحالة المستقرة.
  • نقطة الانعطاف / نقطة الركبة: النقطة التي يبدأ عندها p99 في الانحراف الحاد عن p50 وp95. هذا هو بداية ظاهرة التطابق في الطابور — النظام يقترب من حد معالجته وتبدأ الطلبات بالانتظار. هذه هي نقطة التشبع.
  • مدى التباعد: إذا كان p99 يساوي 3-5 أضعاف p50، فهذا تباين متوقع من توقفات جمع المهملات وجدولة نظام التشغيل. أما إذا كان 20 ضعفاً أو أكثر عند حمل متوسط، فلديك مشكلة هيكلية: تنافس على الأقفال، أو نفاد مجموعة اتصالات قاعدة البيانات، أو خدمة مجرى أسفل أحادية الخيط.
زمن استجابة ذيل التوزيع يخبرك عن أسوأ العملاء المتضررين، وليس متوسط العملاء. p50 يساوي 30 مللي ثانية يعني أن نصف مستخدميك سريعون. p99 يساوي ثانيتين يعني أن طلباً واحداً من كل 100 بطيء جداً — ولخدمة تعالج 1000 طلب في الثانية، هذا يعني 10 طلبات بطيئة كل ثانية. p99 هو الرقم الذي كُتبت عليه اتفاقية مستوى الخدمة، وهو الرقم الذي يجب تحسينه.

تحديد نقاط التشبع

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

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

# سكريبت k6 للزيادة التدريجية: يُستخدم لتحديد نقطة التشبع تلقائياً # شغّله، ثم افحص مخرجات CSV لإيجاد أين يتجاوز p99 ضعف قيمته الأساسية import http from 'k6/http'; import { check, sleep } from 'k6'; export const options = { stages: [ { duration: '2m', target: 100 }, // إحماء { duration: '3m', target: 300 }, { duration: '3m', target: 500 }, { duration: '3m', target: 700 }, // التشبع المتوقع هنا لعقدة 4 vCPU نموذجية { duration: '3m', target: 900 }, { duration: '2m', target: 0 }, // تبريد — راقب وقت الاسترداد أيضاً ], thresholds: {}, // لا بوابات؛ هذا تشغيل استكشافي }; export default function () { const res = http.get('http://api-svc:8080/v1/healthz'); check(res, { 'status 200': (r) => r.status === 200 }); sleep(0.1); }

بعد التشغيل، استخرج نقطة انعطاف التشبع برمجياً بدلاً من تخمينها بصرياً:

#!/usr/bin/env python3 # find_saturation.py — يقرأ مخرجات k6 CSV، يجد أول نافذة 30 ثانية # يتجاوز فيها p99 ضعف قيمة p99 الأساسية (المقاسة خلال المرحلة الأولى). # الاستخدام: k6 run --out csv=results.csv ramp.js && python3 find_saturation.py results.csv import sys, csv, statistics WINDOW_SECONDS = 30 SATURATION_MULTIPLIER = 2.0 buckets = {} with open(sys.argv[1]) as f: reader = csv.DictReader(f) for row in reader: if row.get('metric_name') != 'http_req_duration': continue t = int(float(row['timestamp'])) // WINDOW_SECONDS * WINDOW_SECONDS buckets.setdefault(t, []).append(float(row['metric_value'])) windows = sorted(buckets) if len(windows) < 2: print("بيانات غير كافية"); sys.exit(1) baseline_p99 = statistics.quantiles(buckets[windows[0]], n=100)[98] print(f"القيمة الأساسية p99: {baseline_p99:.1f} مللي ثانية") for t in windows[1:]: p99 = statistics.quantiles(buckets[t], n=100)[98] rps = len(buckets[t]) / WINDOW_SECONDS if p99 >= baseline_p99 * SATURATION_MULTIPLIER: print(f"تم رصد التشبع عند t={t} ثانية، ~{rps:.0f} طلب/ثانية، p99={p99:.1f} مللي ثانية") break else: print("لم يُرصد تشبع — النظام تحمّل كامل نطاق الحمل")
في Google وNetflix، تُتبَّع نقاط التشبع لكل إصدار كرقم واحد: "هذه الخدمة تتشبع عند N طلب في الثانية لكل نسخة." نسبة ذروة حركة المرور الحالية إلى هذا الرقم هي معدل استخدام النسخة. إذا تجاوز الاستخدام 60-70%، يُشغَّل تخطيط الطاقة فوراً — وليس بعد وقوع حادثة. ابنِ هذا الرقم في دفاتر التشغيل.

قياس هامش الطاقة والتواصل بشأنه

هامش الطاقة هو الفجوة بين ذروة الحمل الملاحظة حالياً ونقطة التشبع، مُعبَّراً عنها كنسبة مئوية من نقطة التشبع. هامش 40% يعني أنك تستطيع استيعاب 40% من حركة مرور إضافية قبل أن يتدهور الأداء. هامش 5% يعني أن ارتفاعاً واحداً غير متوقع في حركة المرور — تغريدة فيروسية، أو موجة إعادة محاولة من مكوّن مجاور، أو تفريغ ذاكرة التخزين المؤقت — سيضعك في حادثة.

المعادلة بسيطة: الهامش = (طلبات/ث عند التشبع - ذروة طلبات/ث الحالية) / طلبات/ث عند التشبع × 100. الفن يكمن في الاتفاق على ما يعنيه "الذروة الحالية": استخدم p99 لذروة طلباتك في الساعة خلال آخر 30 يوماً، وليس المتوسط، وليس تقديراً اصطناعياً.

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

# PromQL: احسب هامش الطاقة مقابل طلبات/ث التشبع المقاسة # يفترض وجود قاعدة تسجيل: job:http_requests:rate1m # وقيمة ثابتة في مقياس: service_saturation_rps{job="checkout-api"} = 630 ( service_saturation_rps{job="checkout-api"} - max_over_time(job:http_requests:rate1m{job="checkout-api"}[30d]) ) / service_saturation_rps{job="checkout-api"} * 100
الهامش المحسوب من اختبار حمل يُجرى في بيئة التجهيز ليس هو هامش الإنتاج. في الإنتاج توجد جلسات مستخدم حقيقية، وحالة إحماء ذاكرة التخزين المؤقت، ومهام خلفية، وتعدد اتصالات لا تُحاكيها بيئة التجهيز عادةً. دائماً قم بالمعايرة: شغّل اختبار الزيادة التدريجية نفسه مقابل إعادة تشغيل حركة مرور الإنتاج وقارن نقاط التشبع بين البيئتين. فارق 20% أمر شائع؛ فارق 60% يعني أن بيئة التجهيز غير تمثيلية وأن جميع قرارات الميزانية المبنية عليها مشكوك فيها.

كتابة تقارير أداء تدفع اتخاذ القرارات

تقرير الأداء الذي لا يؤدي إلى قرار هو جهد ضائع. هيكل كل تقرير حول ثلاثة أقسام: النتائج (ما تُظهره البيانات، بأرقام ملموسة ورسوم بيانية مُعلَّقة)، تقييم المخاطر (نسبة الهامش المئوية، الوقت حتى النفاد بمعدل النمو الحالي، أي شريحة مئوية هي الأقرب لخرق اتفاقية مستوى الخدمة)، والإجراءات الموصى بها (مرتبة حسب نسبة التأثير إلى الجهد، مع مالك وموعد نهائي). تجنب الصفات — "زمن الاستجابة مرتفع" لا معنى له؛ "p99 عند 600 طلب/ثانية هو 340 مللي ثانية، أي 36% فوق ميزانية 250 مللي ثانية" قابل للتنفيذ.

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

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