أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
Optimizing بالعربي

Tail Latency للمحترف: ليه P99 يكسر 5% من مستخدميك

📅 ٨ مايو ٢٠٢٦⏱ 6 دقائق قراءة
Tail Latency للمحترف: ليه P99 يكسر 5% من مستخدميك
المستوى المطلوب: محترف. المقال ده مكتوب لمهندسين بيشتغلوا على API في إنتاج، عندهم monitoring stack شغّال (Prometheus وGrafana أو ما يشبههم)، وعارفين يقروا histogram. لو لسه مبتدئ، اقرأه عشان تفهم الإطار، وارجع له تاني لما تواجه أول شكوى "الموقع بطيء" من غير ما تلاقي حاجة في الـ dashboard.

لو الـ API عندك بيرد في 80ms متوسط، وعميل بيتصل يقولك إن صفحة الطلبات بتعلّق عنده، إنت مش هتلاقي حاجة في الـ Grafana. المشكلة إن المتوسط بيخفي كارثة بتحصل لـ 1 من كل 100 طلب — ودي بالظبط الكارثة اللي بتكسر ثقة 5% من قاعدة مستخدميك.

Tail Latency: المعدل بيخبّي الكارثة

شاشة مراقبة تعرض رسم بياني لزمن الاستجابة P50 و P95 و P99 لخدمة API في إنتاج

المشكلة باختصار

في كل API بتقدّمه، فيه ذيل (tail) من الطلبات بتاخد زمن أعلى بكتير من المتوسط. ده مش noise، وده مش edge case هتتجاهله. ده اللي بيحدّد تجربة فعلية لشريحة من مستخدميك. كل 100 طلب فيهم 5 طلبات أبطأ من P95، وواحد بيتعدى P99. لو P50 = 80ms و P99 = 2400ms، إنت في إنتاج بيقع — بس ما حدش لسه بيشوفه في الـ metrics.

مثال بسيط للمبتدئ قبل الكلام العلمي

تخيل خط إنتاج بيركّب 1000 موبايل في الساعة. لو مدير المصنع بيقولك "متوسط زمن التركيب 36 ثانية"، الكلام ده مفيد للتسويق. لكن لو 10 موبايلات في الساعة بياخدوا 5 دقايق لأن في عقدة في الـ pipeline (آلة بتسخن، أو عامل بياخد break)، العملاء اللي استلموا الـ 10 دول هم اللي هيكتبوا review سيء. المتوسط مش بيشوفهم. P99 بيشوفهم.

الفكرة بالظبط زي كده في الـ API. متوسط الاستجابة بيقولك إن "الجو حلو". P99 بيقولك "في حد بيتعذّب".

التعريف العلمي للنسب المئوية

الـ Latency Percentiles هي توزيع statistical لزمن الاستجابة. P50 (الوسيط) هو القيمة اللي 50% من الطلبات أسرع منها. P99 = 99% من الطلبات أسرع، يعني 1% من الطلبات أبطأ. الفجوة بين P50 و P99 اسمها tail.

الافتراض المهم: زمن الاستجابة في إنتاج مش بيتبع توزيع طبيعي (Normal Distribution). التوزيع long-tailed، يعني الفرق بين P50 و P99 ممكن يوصل 10x أو أكتر. ده مش رأي شخصي، ده مرصود من عشرات الشركات ومؤرّخ في ورقة Jeffrey Dean و Luiz André Barroso بعنوان "The Tail at Scale" (CACM، فبراير 2013).

رسم بياني يوضح توزيع long-tail لزمن الاستجابة وفجوة كبيرة بين P50 و P99 في خدمة منتجة

السيناريو الواقعي بالأرقام

افترض إن service عندك بيخدّم 5000 طلب/ثانية. P50 = 80ms، P99 = 2400ms. في كل ثانية، 50 طلب بياخدوا أكتر من 2.4 ثانية. في ساعة واحدة، 180,000 طلب بطيء. في يوم، 4.3 مليون طلب. مش edge case — ده شريحة كاملة من تجربة الاستخدام بتتدمّر يوميًا.

والـ trade-off اللي مش معلن في معظم الأنظمة: لو عندك 10 microservices متسلسلة في رحلة الطلب الواحد وكل واحدة P99 = 100ms، الـ end-to-end P99 مش 100ms. هو أقرب لـ 700ms لأن احتمال إن طلب واحد على الأقل يقع في tail خدمة من الـ 10 بيتراكم بشكل multiplicative. ده اللي خلّى Dean و Barroso يحذّروا من "tail amplification" في الورقة.

القياس بأداة حقيقية

الأداة المعتمدة من LinkedIn و Grafana Labs لقياس percentiles بدقة تحت ضغط هي k6 أو wrk2. لازم تستخدم أداة بتعمل coordinated omission correction، عشان مفيش حاجة اسمها "متوسط الاستجابة" تحت الضغط من غير التصحيح ده (راجع كلام Gil Tene في Strange Loop 2015).

JavaScript
import http from 'k6/http';

export const options = {
  vus: 200,
  duration: '2m',
  thresholds: {
    'http_req_duration': [
      'p(50)<100',
      'p(95)<400',
      'p(99)<800',
    ],
  },
};

export default function () {
  http.get('https://api.example.com/orders/recent');
}

التشغيل: k6 run latency.js. الناتج بيرجّع P50 و P95 و P99 منفصلين. لو ولا threshold اتكسر، k6 بيرجع exit code != 0 — يعني تقدر تحطها في CI كـ gate قبل الـ deploy.

3 أسباب شائعة لارتفاع P99

  1. Garbage Collection pauses: في الـ JVM وNode.js وGo، الـ GC بيوقف الـ thread لمدة 10-200ms. هتلاقي الـ P99 بيقفز بانتظام عند موعد الـ collection. الحل: monitoring لـ GC pause times، tuning للـ heap size، أو الانتقال لـ low-pause collector زي ZGC أو Shenandoah في الـ JVM.
  2. Connection pool exhaustion: لو الـ pool عندك 50 اتصال DB وفيه 60 طلب متزامن، 10 طلبات بيستنوا في queue. الـ P50 ما يحسش، الـ P99 بيتضاعف لأن الطلبات اللي في الذيل هي اللي بتستنى الـ pool يفضى. الحل: قِس saturation للـ pool في Grafana، وارفع الحجم قبل ما يوصل 80%.
  3. Cold cache بعد TTL expiration: أول طلب بعد انتهاء الـ TTL بياخد 800ms من الـ DB، باقي الطلبات في الـ TTL window بياخدوا 8ms من الكاش. ده بيظهر كـ spike دوري في الـ P99 كل فترة TTL. الحل: stale-while-revalidate أو background refresh قبل انتهاء الـ TTL.

الـ trade-offs لما تحاول تحسّن P99

تحسين الـ P99 له ثمن، ولازم يكون واضح قبل ما تبدأ.

بتكسب: تجربة أفضل لـ 1% من الطلبات. ده ممكن يكون 1% من المستخدمين الـ B2C (لو الطلبات موزعة بالتساوي)، أو شريحة كاملة من العملاء الـ B2B لو request واحد بيدخل في رحلة طويلة.

بتخسر: زيادة في استهلاك الذاكرة لو زوّدت connection pool أو heap. زيادة في تكلفة الـ infrastructure لو ضفت replicas. زيادة في complexity العملية لو طبّقت hedged requests (إرسال نفس الطلب لـ 2 servers والاكتفاء بالأسرع — التكلفة 2x للـ backend، والتوفير في latency حقيقي بس الفاتورة مضاعفة).

قاعدة عملية: لو شغلك B2C وفيه monetization مرتبط بكل طلب (بحث، شراء، مشاهدة)، تحسين P99 له ROI مباشر وقابل للقياس. لو شغلك internal tooling أو batch jobs، ركّز على throughput و P50 وسيب P99 لحالها.

متى لا تركّز على P99

  • Batch processing: مفيش user جالس مستني. ركّز على throughput و time-to-completion للـ batch كاملاً.
  • Async fire-and-forget endpoints: اللي بترجع 202 Accepted وبتشتغل في الخلفية. الـ P99 لـ accept response ميه يعني، الزمن الحقيقي في الـ worker.
  • Endpoints بتاعت admin أو internal: أقل من 100 طلب/يوم، الـ percentiles مش statistically significant — أي طلب بطيء بيظهر كـ P99 خادع.
  • Endpoints بترجع stream طويل: TTFB أهم من total duration، استخدم metric مختلف.

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

افتح الـ Grafana بتاعك دلوقتي، وضيف panel جديد لكل critical endpoint بـ 4 خطوط: P50, P95, P99, P999. لو نسبة P99/P50 أكتر من 5x، عندك tail latency حقيقي. اكتب اسم الـ endpoint والنسبة الحالية والهدف اللي عايزه. وابدأ بالسبب رقم 2 من الجدول فوق (connection pool) — في 80% من الحالات هو الـ low-hanging fruit.

المصادر

  • Dean, J. & Barroso, L. A. (2013). "The Tail at Scale". Communications of the ACM, 56(2), 74-80.
  • Tene, G. (2015). "How NOT to Measure Latency". Strange Loop conference talk.
  • k6 documentation, Thresholds reference: https://grafana.com/docs/k6/latest/using-k6/thresholds/
  • Prometheus documentation, histogram_quantile() function reference.
  • Brendan Gregg, "Systems Performance" (2nd ed., 2020), Chapter 2: Methodologies — discussion on percentiles vs averages.
]]>

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة