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

عقلية هندسة الأداء

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

عقلية هندسة الأداء

الأداء ليس ميزةً تُضاف في نهاية دورة الإصدار. في Google وAmazon وNetflix، يُعامَل الأداء باعتباره متطلبًا من متطلبات الصحة الوظيفية — فالنظام الذي يُعيد الإجابة الصحيحة في 30 ثانية هو نظام خاطئ لمعظم الأغراض. يبني هذا الدرس الأساس المفاهيمي الذي تحتاجه قبل لمس أي أداة لاختبار الحمل: المصطلحات الدقيقة للأداء (زمن الاستجابة، والإنتاجية، والنسب المئوية)، والتكلفة الاقتصادية للبطء، والنماذج الذهنية التي تُميّز المهندسين القادرين على إيجاد الاختناقات الحقيقية عمّن يتتبعون الضوضاء.

زمن الاستجابة مقابل الإنتاجية — محوران مستقلان

زمن الاستجابة (Latency) هو الوقت المنقضي من لحظة إرسال الطلب حتى استلام استجابة كاملة، ويُقاس دائمًا من منظور العميل. إنه خاصية طلب واحد.

الإنتاجية (Throughput) هي معدل إنجاز النظام للعمل — عادةً الطلبات في الثانية (RPS)، أو المعاملات في الثانية (TPS)، أو الرسائل في الثانية. إنها خاصية النظام تحت حِمل معيّن.

هذان المحوران مترابطان لكنهما ليسا متطابقَين. يصف قانون Little العلاقة بدقة:

# قانون Little: # L = λ × W # # L = متوسط عدد الطلبات في النظام (التزامنية) # λ = الإنتاجية (وصول في الثانية = طلبات/ثانية في الحالة المستقرة) # W = متوسط زمن الاستجابة (ثانية/طلب) # # مثال: الخدمة تعالج 1,000 طلب/ثانية بزمن استجابة متوسط 50 مللي ثانية # L = 1000 × 0.050 = 50 طلبًا نشطًا في أي لحظة # # النتيجة: لمضاعفة الإنتاجية بنفس زمن الاستجابة، # يجب أن تكون قادرًا على استيعاب ضعف عدد الطلبات المتزامنة. # إذا كان حجم تجمع الخيوط 50، فإن مضاعفة طلبات/ثانية # ستراكم الطلبات في قائمة الانتظار وسيرتفع زمن الاستجابة بشكل غير خطي.
قانون Little محايد تقنيًا وينطبق على أي نظام انتظار — حاوية Kubernetes، أو تجمع اتصالات قاعدة البيانات، أو موزع الحمل، أو مسار الدخول على الطريق السريع. في كل مرة تزيد فيها الإنتاجية دون زيادة الطاقة، يرتفع زمن الاستجابة. احتفظ بهذا المثلث في ذهنك دائمًا.

لماذا المتوسطات كاذبة: الحالة في صالح النسب المئوية

أهم عادة يمكنك اكتسابها هي عدم الثقة بأرقام متوسط زمن الاستجابة قط. المتوسط يخفي التوزيع. خدمة بمتوسط زمن استجابة 20 مللي ثانية يمكن أن تُقدّم ردودًا تستغرق 5 ثوانٍ لنسبة كبيرة من المستخدمين إذا كان التوزيع ذا ذيل طويل.

المعيار الصناعي هو الإبلاغ عن زمن الاستجابة كنسب مئوية:

  • p50 (الوسيط): زمن الاستجابة الذي يختبره المستخدم "النموذجي". نصف الطلبات أسرع ونصفها أبطأ.
  • p95: 95% من الطلبات تكتمل ضمن هذا الوقت. مستخدم من كل 20 يرى على الأقل هذا الزمن.
  • p99: الحد الذي تبقى دونه 99% من الطلبات. عند 1,000 طلب/ثانية، نحو 10 مستخدمين في الثانية يتجاوزون هذا الرقم.
  • p999 (p99.9): عند 10,000 طلب/ثانية، 10 مستخدمين في الثانية يصلون إليه. للخدمات عالية الحركة هذا الرقم هو ما يقود انتهاكات اتفاقيات مستوى الخدمة وشكاوى المستخدمين.
  • p9999 / القيمة القصوى: أسوأ حالة. مهم للمعاملات المالية والأنظمة الحرجة أو أي سير عمل يُعيق فيه رد واحد بطيء العمل المتسلسل.

مثال إنتاجي ملموس: خدمة دفع في متجر إلكتروني كبير قد تُبلّغ عن p50=12 مللي ثانية، p99=180 مللي ثانية، p999=4,200 مللي ثانية. المتوسط هو 22 مللي ثانية. الإبلاغ بـ"خدمتنا لديها زمن استجابة 22 مللي ثانية" يخفي حقيقة أن مستخدمًا من كل 1,000 ينتظر أكثر من 4 ثوانٍ — عند ذروة 50,000 طلب/ثانية، هذا 50 مستخدمًا في الثانية يختبرون توقفًا مدته 4 ثوانٍ في صفحة الدفع.

Latency percentile distribution showing long tail Latency (ms) Request Count p50 12 ms p99 180 ms p999 4,200 ms mean 22 ms long tail (hidden by mean)
توزيع زمن استجابة واقعي: يقع المتوسط بالقرب من القمة، لكن الذيل الطويل يمتد حتى p99.9 إلى 350 ضعف الوسيط — مخفي عن أي لوحة تعتمد على المتوسطات.
مدرّجات Prometheus مقسّمة مسبقًا. دقة histogram_quantile(0.99, ...) تعتمد كليًا على حدود الحاويات التي عرّفتها. إذا توقفت حاوياتك عند 1 ثانية وكان p99 الفعلي 2 ثانية، سيُعيد Prometheus 1 ثانية بصمت. عرّف دائمًا حاوية واحدة على الأقل أعلى من أسوأ زمن استجابة متوقع. نمط شائع هو مضاعفة الحاويات: 5، 10، 25، 50، 100، 250، 500 مللي ثانية، ثم 1، 2.5، 5، 10 ثوانٍ.

الاقتصاد السياسي للبطء

مشاكل الأداء لها تأثير مباشر على الإيرادات. وجدت فرق هندسة Amazon أن كل 100 مللي ثانية إضافية في تحميل الصفحة تكلّف حوالي 1% من المبيعات. Google أفادت بأن تأخيرًا نصف ثانية في نتائج البحث يُقلّل حركة المرور بنسبة 20%. هذه الأرقام من العقد الأول من الألفية الثالثة — وتحمل المستخدمين للبطء لم يزدد إلا انخفاضًا منذ ذلك الحين.

الإطار الحديث هو نموذج Core Web Vitals: خوارزمية ترتيب Google تعاقب الصفحات التي يتجاوز فيها Interaction to Next Paint (INP) 200 مللي ثانية وLargest Contentful Paint (LCP) 2.5 ثانية. البطء الآن تكلفة SEO مباشرة، وليس مجرد تكلفة تجربة مستخدم.

على مستوى البنية التحتية، للبطء تأثير مُركّب عبر تضاعف زمن الاستجابة المتتالية. في معمارية الخدمات المصغّرة حيث يتفرع طلب مستخدم واحد إلى 10 استدعاءات متوازية، فإن زمن الاستجابة الإجمالي يتبع الحد الأقصى للاستدعاءات المتوازية لا المتوسط. إذا كان p99 لكل خدمة 50 مللي ثانية، فإن احتمال أن يصل واحد على الأقل من 10 استدعاءات متوازية إلى p99 هو تقريبًا 1 − (0.99)^10 ≈ 9.6 % — أي أن p99 المُركّب هو فعليًا p90 الفردي. هذه هي مشكلة تضخيم الذيل التي يجب أن يستوعبها كل مهندس أول في شركة تعتمد الخدمات.

الحل الكلاسيكي لتضخيم الذيل هو نمط الطلب المُسيَّج (hedged request)، أو "طلبات الاحتياط": بعد تأخير قصير (مثلاً نسبة p95 من زمن الاستجابة)، أرسل طلبًا ثانيًا مطابقًا إلى نسخة مختلفة واستخدم الاستجابة التي تصل أولاً. Google Bigtable وCassandra والعديد من شبكات الخدمات القائمة على Envoy تدعم هذا النمط بشكل أصلي. المقايضة هي زيادة الحمل على الخلفية — عادةً 5-10% طلبات إضافية لتحقيق انخفاض كبير في زمن الاستجابة المتأخر. طبّقه فقط على مسارات القراءة ذات الطابع اللاأثري (idempotent).

الربط بما تعلمته بالفعل

كل ما درسته في هذه الدورة يُغذّي هندسة الأداء:

  • Prometheus + Grafana: أدواتك الأساسية لمراقبة النسب المئوية في الإنتاج. دالة histogram_quantile ولوحات RED (المعدل والأخطاء والمدة) هي نقطة الدخول لكل تحقيق في الأداء.
  • حدود موارد Kubernetes: تقييد وحدة المعالجة المركزية على مستوى cgroup هو أحد أكثر مساهمي زمن الاستجابة الخفية شيوعًا في أحمال العمل المُحتواة. الحاوية التي تعمل عند حد وحدة المعالجة لا تتباطأ تدريجيًا — تتراكم الطلبات في قائمة الانتظار ويرتفع زمن الاستجابة بشكل غير خطي.
  • التتبع الموزع (Jaeger/Tempo): مقاييس النسب المئوية تخبرك أن شيئًا ما بطيء؛ التتبعات تخبرك أين. الأداتان مكمّلتان لا متكررتان.
  • مستويات خدمة SLO من مبادئ SRE: اتفاقية زمن الاستجابة (مثلاً "p99 أقل من 200 مللي ثانية على مدى 30 يومًا") هي التعبير الرسمي عن عقد الأداء. اختبار الحمل يتحقق من قدرتك على تحقيق هذا الاتفاق تحت حركة مرور واقعية.
# فحص سريع: استعلام p99 لزمن الاستجابة لخدمة في Prometheus # (يفترض مقياس مدرج قياسي http_request_duration_seconds) histogram_quantile( 0.99, sum by (le, service) ( rate(http_request_duration_seconds_bucket{service="checkout"}[5m]) ) ) # إذا أعاد NaN، فحاوياتك لا تغطي نطاق زمن الاستجابة الفعلي. # تحقق: max(http_request_duration_seconds_bucket{le="+Inf"}) مقابل أعلى حاوية محدودة لديك. # الإنتاجية لنفس الخدمة: sum(rate(http_request_duration_seconds_count{service="checkout"}[5m])) by (service) # نسبة الأخطاء (مكمّل معدل النجاح): 1 - ( sum(rate(http_request_duration_seconds_count{service="checkout", status_code=~"2.."}[5m])) / sum(rate(http_request_duration_seconds_count{service="checkout"}[5m])) )

سير عمل هندسة الأداء

قبل تشغيل اختبار حمل واحد، حدّد ثلاثة أشياء:

  1. حدّد اتفاقية مستوى الخدمة (SLO): ما زمن الاستجابة المقبول عند أي نسبة مئوية، وتحت أي تزامنية، ولأي ميزانية أخطاء؟ بدون هدف ملموس لا يمكنك إعلان النجاح أو الفشل.
  2. أنشئ خطًا أساسيًا: قِس النظام تحت حركة مرور تمثّل الإنتاج الآن، قبل أي تغييرات. لا يمكنك تحسين ما لم تقسه، ولا يمكنك تأكيد تحسين بدون خط أساسي.
  3. حدّد فرضية الاختناق: استخدم بيانات المراقبة الحالية (اللوحات والتتبعات وعينات المُحلّل) لصياغة فرضية محددة حول مكان القيد. اختبار الحمل بدون فرضية يُنتج ضوضاء؛ اختبار الحمل بفرضية يُنتج إشارة.

الدروس المتبقية في هذا البرنامج التعليمي تُجسّد كل خطوة من هذه الخطوات — k6 وJMeter للحمل الاصطناعي، وأدوات التحليل لداخليات التطبيق، والتقارير المنظّمة لإغلاق حلقة التغذية الراجعة مع أصحاب المصلحة. النماذج الذهنية في هذا الدرس هي العدسة التي من خلالها سيُفسَّر كل شيء آخر.