اختبار السعة وقابلية التوسع

اختبار السعة (Capacity Testing) يقيس أقصى حمل يستطيع النظام تحمّله وهو لا يزال يحقق أهداف الأداء. والإجابة رقم مقرون بشروطه، مثل: «واجهة الطلبات على أربعة خوادم تطبيق تتحمل ⁦1,450⁩ طلباً في الثانية، مع p95 أقل من ⁦500⁩ مللي ثانية وأخطاء أقل من ⁦0.5%⁩، لمزيج الطلبات المتفق عليه». وعند الخطوة التالية من الحمل يسقط أحد الأهداف.

أما اختبار قابلية التوسع (Scalability Testing) فيسأل كيف يتغير هذا الرقم عند إضافة موارد أو عند نمو العمل: هل تعطي ثمانية خوادم ضعف سعة أربعة؟ وهل تبقى الاستعلامات سريعة عندما تحوي قاعدة البيانات عشرة أضعاف الصفوف؟ ومعاً يمنح الاختباران تخطيطَ السعة قياسات بدلاً من التخمين.

لماذا يهم

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

ويصبح سؤال المختبِر: «كم يتحمل النظام، وأيّ مورد ينفد أولاً، وماذا نكسب بإضافة المزيد؟». فقد كشف اختبار الإجهاد أين ينهار النظام، وكشف اختبار التحمّل هل يصمد مع الوقت؛ أما اختبار السعة وقابلية التوسع فيكشفان الحدّ القابل للاستخدام قبل الانهيار، وهل تستطيع البنية أن تنمو إلى ما بعده.

السعة: أقصى حمل لا يزال يحقق الأهداف

يصف منهج ISTQB لاختبار الأداء اختبارَ السعة بأنه تحديد عدد المستخدمين أو المعاملات أو كليهما الذي يدعمه النظام مع بقائه محققاً لأهداف الأداء المعلنة، ويمكن أن تُصاغ هذه الأهداف أيضاً بأحجام البيانات. ويضع المعيار ISO/IEC 25010 السعةَ تحت خاصية كفاءة الأداء، ومن مَعلماتها (Parameters) عدد المستخدمين المتزامنين وإنتاجية المعاملات وحجم قاعدة البيانات. لذا يحدد كل اختبار سعة البُعد الذي يقيسه.

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

  • ثبّت الأهداف أولاً، مثل p95 أقل من ⁦500⁩ مللي ثانية والأخطاء أقل من ⁦0.5%⁩. فبدونها لا تجد إلا نقطة الانهيار.
  • استخدم نموذج عبء العمل (Workload Model) من الدروس السابقة: فمزيج يغلب عليه التصفح ومزيج يغلب عليه الدفع يعطيان سعتين مختلفتين.
  • ارفع الحمل على خطوات متساوية، وأبقِ كل خطوة حتى يستقر الأداء، مثلاً ⁦10⁩ دقائق، فتصبح كل خطوة اختبار حمل صغيراً.
  • سجّل لكل خطوة: الإنتاجية (Throughput)، وp95 وp99، ومعدل الأخطاء، واستخدام المعالج والذاكرة والاتصالات وقوائم الانتظار. وأول خطوة تفشل تبيّن أيّ هدف سقط وأيّ مورد نفد.

جرّبها: مولّد بيانات اختبار الأداء جرّبها: مولّد اختبارات الطلبات المتزامنة

قابلية التوسع: التوسع الرأسي والتوسع الأفقي

يصف منهج ISTQB لاختبار الأداء اختبارَ قابلية التوسع بأنه التحقق من قدرة النظام على النمو، مثلاً إلى مستخدمين أكثر أو بيانات مخزّنة أكبر، لتلبية متطلبات مستقبلية تتجاوز متطلبات اليوم دون أن يخالف متطلبات الأداء الحالية أو يُخفق. ويضع المعيار ISO/IEC 25010:2023 قابليةَ التوسع (Scalability) خاصيةً فرعية تحت المرونة (Flexibility). وفي الواقع العملي يُلبّى هذا النمو بإضافة الموارد بإحدى طريقتين.

فالتوسع الرأسي (Vertical Scaling أو Scale Up) يمنح خادماً واحداً معالجاً أقوى أو ذاكرة أكبر أو تخزيناً أسرع: لا تغيير في الشيفرة، لكنّ له سقفاً، وتغيير الحجم يتطلب غالباً إعادة تشغيل، ويبقى الخادم نقطة إخفاق وحيدة (Single Point of Failure). أما التوسع الأفقي (Horizontal Scaling أو Scale Out) فيضيف مثيلات (Instances)، أي نسخاً متطابقة من التطبيق، خلف موازن الحمل (Load Balancer): لا سقف ثابتاً له، لكن يجب أن تكون المثيلات عديمة الحالة (Stateless)، أي لا تُحفظ جلسة المستخدم في ذاكرة مثيل بعينه، والأجزاء المشتركة مثل قاعدة البيانات أو واجهة برمجية خارجية محدودة المعدل لا تتضاعف معها.

يشغّل اختبار قابلية التوسع اختبار السعة نفسه على عدة أحجام، ويغيّر شيئاً واحداً في كل مرة: ⁦1⁩ و⁦2⁩ و⁦4⁩ و⁦8⁩ مثيلات، أو ⁦4⁩ و⁦8⁩ و⁦16⁩ vCPU (أنوية معالج افتراضية)، مع البيانات والمزيج والأهداف نفسها. وقارن بين الأحجام بكفاءة التوسع efficiency = C(N) / (N × C(1))، حيث C(N) هي السعة مع N وحدة؛ وتعني ⁦100%⁩ أن كل وحدة تضيف نصيبها كاملاً.

  • التوسع الرأسي: تحقّق من أن البرنامج يستخدم الموارد الجديدة. فمجمّع الخيوط (Thread Pool) ثابت الحجم، أي العدد المحدد من خيوط العمل التي تخدم الطلبات في الوقت نفسه، قد يترك الأنوية المضافة خاملة.
  • التوسع الأفقي: تحقّق من أن الجلسة تبقى عندما يصل الطلب إلى مثيل آخر، وأن المهام المجدولة لا تعمل مرة لكل مثيل.
  • التوسع مع البيانات: أعد الاختبار بحجم البيانات المتوقع للسنة القادمة؛ فاستعلام سريع على مليون صف قد لا يبقى سريعاً على عشرين مليوناً.

جرّبها: مولّد بيانات اختبار التحميل جرّبها: مولّد مجموعات بيانات JSON الكبيرة

مثال تطبيقي: واجهة الطلبات قبل موسم التخفيضات

يتوقع متجر إلكتروني ذروة قدرها ⁦1,800⁩ طلب في الثانية على واجهة الطلبات البرمجية خلال تخفيضاته السنوية. والهدف: p95 أقل من ⁦500⁩ مللي ثانية والأخطاء أقل من ⁦0.5%⁩ لمزيج الطلبات المتفق عليه. وبيئة الاختبار تحاكي الإنتاج: مثيلات تطبيق بأربع وحدات vCPU لكل منها خلف موازن حمل، وخادم قاعدة بيانات واحد بثماني وحدات vCPU، وبيانات بحجم الإنتاج. وقد شغّل الفريق اختبار السعة المتدرج على ⁦1⁩ و⁦2⁩ و⁦4⁩ و⁦6⁩ و⁦8⁩ مثيلات.

  • حتى ⁦4⁩ مثيلات تتوسع الواجهة أفقياً بشكل شبه خطي: طبقة التطبيق هي الحدّ.
  • من ⁦4⁩ إلى ⁦8⁩ مثيلات ترتفع السعة ⁦80⁩ طلباً في الثانية فقط، بينما يبلغ استخدام معالج قاعدة البيانات ⁦98%⁩ ويمتلئ مجمّع اتصالاتها: انتقل عنق الزجاجة (Bottleneck) إلى قاعدة البيانات.
  • تتوقف هذه البنية عند نحو ⁦1,500⁩ طلب في الثانية، أي دون الذروة المتوقعة، ولن يسدّ أي عدد من مثيلات التطبيق هذه الفجوة. فالنتيجة هي «وسّعوا قاعدة البيانات أو خففوا عنها»، لا «أضيفوا خوادم».
  • التجربة التالية: امنح قاعدة البيانات موارد أكثر أو عملاً أقل، مثلاً بإضافة فهرس ناقص أو بالتخزين المؤقت لقراءات المنتجات، ثم أعد التشغيل على ⁦4⁩ و⁦6⁩ و⁦8⁩ مثيلات.
Objective: p95 < 500 ms and errors < 0.5 % (agreed request mix)

Instances  Capacity (req/s)  Efficiency  Saturated first
    1             400           100 %    app CPU 92 %
    2             780            98 %    app CPU 90 %
    4           1,450            91 %    DB CPU 88 %
    6           1,520            63 %    DB CPU 97 %
    8           1,530            48 %    DB CPU 98 %, DB pool full

Efficiency = capacity / (instances x 400)
Forecast peak for the sale: 1,800 req/s

قراءة منحنى التوسع

ارسم السعة مقابل عدد الوحدات وقارنها بالخط المستقيم للتوسع المثالي. فشكل المنحنى يخبرك بالخطوة التالية.

  • خطي (Linear): كل وحدة تضيف نصيبها كاملاً. يمكن شراء السعة بمزيد من الوحدات ما دامت الأجزاء المشتركة تواكب.
  • دون الخطي (Sub-linear): كل وحدة تضيف أقل قليلاً بسبب التنسيق والموارد المشتركة. التوسع ينجح، لكن كلفة الطلب الواحد ترتفع.
  • الثبات (Plateau): تتوقف السعة عن الارتفاع، كما في المثال التطبيقي. هناك مكوّن مشترك مشبع؛ فابحث عنه ووسّعه، لأن الوحدات الإضافية لا تضيف إلا الكلفة.
  • التراجع (Retrograde): تنخفض السعة مع إضافة الوحدات، وغالباً لأن المثيلات تتنافس على قفل (Lock) أو مجمّع اتصالات. سجّله عيباً.
السعة مقابل عدد نسخ التطبيق في أربعة أشكال: النمو الخطي ودون الخطي يتجاوزان الذروة المتوقعة ⁦1,800⁩ طلب في الثانية، بينما تثبت واجهة الطلبات في المثال قرب ⁦1,530⁩ طلباً في الثانية حين تتشبع قاعدة بياناتها. نموذج مفاهيمي
  1. خطيكل مثيل يضيف ⁦400⁩ طلب في الثانية (كفاءة قريبة من ⁦100%⁩): خمسة مثيلات تبلغ الذروة المتوقعة.

    الخط المرجعي:الذروة المتوقعة: ⁦1,800⁩ طلب في الثانية

  2. دون الخطيكل مثيل يضيف أقل قليلاً (كفاءة ⁦72%⁩ عند ⁦8⁩ مثيلات): ستة مثيلات تعطي ⁦1,860⁩ طلباً في الثانية، بكلفة أعلى للطلب الواحد.

    الخط المرجعي:الذروة المتوقعة: ⁦1,800⁩ طلب في الثانية

  3. الثبات: واجهة الطلباتشبه خطي حتى ⁦4⁩ مثيلات، ثم ثابت قرب ⁦1,530⁩ طلباً في الثانية مع تشبع قاعدة البيانات: لا يبلغ أي عدد من المثيلات الذروة المتوقعة.

    الخط المرجعي:الذروة المتوقعة: ⁦1,800⁩ طلب في الثانية

  4. التراجعبعد ⁦4⁩ مثيلات تنخفض السعة لأن المثيلات تتنافس على قفل أو مجمّع اتصالات: الموارد الإضافية تزيد الوضع سوءاً.

    الخط المرجعي:الذروة المتوقعة: ⁦1,800⁩ طلب في الثانية

    مثيلات أكثر وسعة أقل

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

من نتائج الاختبار إلى خطة السعة

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

ويقدّم المختبِر هذا النصف الثاني في صورة بيان سعة: «⁦400⁩ طلب في الثانية لكل مثيل بأربع وحدات vCPU لمزيج الطلبات المتفق عليه، بتوسع شبه خطي حتى ⁦4⁩ مثيلات؛ وتتوقف البنية عند نحو ⁦1,500⁩ طلب في الثانية لأن معالج قاعدة البيانات يتشبع».

  • هامش الأمان (Headroom): كم يجب أن يبقى حمل الإنتاج في الذروة دون السعة المختبَرة. وهو قرار يتخذه الفريق؛ فبسقف ⁦80%⁩ تحتاج ذروة متوقعة قدرها ⁦1,800⁩ طلب في الثانية إلى سعة مختبَرة قدرها ⁦2,250⁩ طلباً في الثانية.
  • الوحدات الاحتياطية: مثيل واحد زيادة على الحساب (N+1)، حتى يبقى ما يكفي من السعة إذا تعطّل مثيل.
  • مهلة التوفير (Lead Time): دقائق لإضافة مثيل بالتوسع التلقائي، وربما أسابيع لقاعدة بيانات أكبر. والمورد الأبطأ هو ما يحدد متى يجب أن تبدأ الخطة.
  • عتبات الإنتاج: يذكر منهج ISTQB أنه بعد معرفة حدود التوسع يمكن مراقبة عتبات في الإنتاج، مثل تنبيه عندما يتجاوز معالج قاعدة البيانات ⁦75%⁩.

أخطاء شائعة

  • الإبلاغ عن نقطة الانهيار على أنها السعة. فالسعة آخر حمل يحقق كل الأهداف، وهي أقل بكثير من الحمل الذي تنفجر عنده الأخطاء.
  • ذكر السعة دون شروطها. فعبارة «النظام يتحمل ⁦1,500⁩ مستخدم» لا معنى لها دون مزيج الطلبات وحجم البيانات وأحجام الخوادم والأهداف.
  • افتراض التوسع الخطي: ضرب نتيجة المثيل الواحد بدلاً من قياس عدة أحجام.
  • تغيير عدة أشياء بين التشغيلات، كعدد المثيلات وإصدار الشيفرة، فلا يمكن تفسير التغير في السعة.
  • اختبار التوسع الأفقي على قاعدة بيانات صغيرة أو شبه فارغة، فلا تصبح المكونات المشتركة هي الحدّ أبداً.
  • مراقبة خوادم التطبيق وحدها. فبدون مقاييس قاعدة البيانات ومجمّع الاتصالات ترى الثبات ولا ترى سببه.

من منظور ضمان الجودة

تُخطَّط اختبارات السعة وقابلية التوسع مع المطورين وفريق العمليات (DevOps أو SRE)، لأنها تحتاج إلى بيئة شبيهة بالإنتاج ومراقبة، وغالباً إلى ميزانية. ويقدّم المختبِر الأهداف ونموذج عبء العمل وخطة الخطوات، ويتحقق من أن البيئة والبيانات ممثِّلة للإنتاج. واسأل مبكراً: لأي توقع نخطط؟ وأي الموارد مسموح لنا بتغييرها؟ وما سرعة إضافة السعة؟

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

تمرين عملي

اقرأ نتيجة توسع رأسي وحدّد الخطوة التالية

المطلوب

اختُبرت خدمة البحث عن المنتجات على مثيل واحد بأربعة أحجام، مع البيانات ومزيج الطلبات نفسها. وهدفها p95 أقل من ⁦300⁩ مللي ثانية والأخطاء أقل من ⁦1%⁩. قيّم مدى نجاح توسعها الرأسي والسعة التي تحتاجها الذروة المتوقعة، ثم اقترح الاختبار التالي.

المادة
Service: product search, one instance, same data and request mix
Objective: p95 < 300 ms and errors < 1 %

vCPU  Capacity (req/s)  CPU at capacity  Thread pool at capacity
  2         250              95 %            38 of 64 busy
  4         480              93 %            61 of 64 busy
  8         610              58 %            64 of 64 busy
 16         620              31 %            64 of 64 busy

Forecast peak next quarter: 900 req/s
Team policy: peak load stays at or below 80 % of tested capacity
الخطوات
  1. احسب كفاءة التوسع لكل حجم مقارنةً بحجم ⁦2⁩ vCPU.
  2. حدّد أين يتوقف التوسع الرأسي عن أن يكون مجدياً، ولماذا.
  3. احسب السعة المختبَرة التي تحتاجها الذروة المتوقعة وفق سياسة الفريق.
  4. اكتب بيان سعة والاختبار التالي.
إظهار الإجابة النموذجية
الإجابة النموذجية

الكفاءة مقارنةً بحجم ⁦2⁩ vCPU: ⁦4⁩ vCPU = ⁦480 ÷ (2 × 250) = 96%⁩؛ ⁦8⁩ vCPU = ⁦610 ÷ (4 × 250) = 61%⁩؛ ⁦16⁩ vCPU = ⁦620 ÷ (8 × 250) = 31%⁩.

التوسع الرأسي مجدٍ حتى ⁦4⁩ vCPU ثم يتوقف. فعند ⁦8⁩ و⁦16⁩ vCPU يبقى المعالج بعيداً عن التشبع (⁦58%⁩ و⁦31%⁩) بينما الخيوط الـ ⁦64⁩ كلها مشغولة: مجمّع الخيوط الثابت يحدّ العمل المتزامن، فتبقى الأنوية الإضافية خاملة.

السعة المختبَرة اللازمة: ⁦900 ÷ 0.8 = 1,125⁩ طلباً في الثانية. وأفضل مثيل واحد بلغ ⁦620⁩ طلباً في الثانية، فلا يلبّي أي حجم مختبَر لمثيل واحد الذروةَ المتوقعة.

البيان: «خدمة البحث، مثيل واحد، البيانات الحالية والمزيج المتفق عليه: ⁦480⁩ طلباً في الثانية عند ⁦4⁩ vCPU، ونحو ⁦620⁩ عند ⁦8⁩ أو ⁦16⁩ vCPU؛ وفوق ⁦4⁩ vCPU يكون الحدّ مجمّعَ الخيوط ذا الـ ⁦64⁩ خيطاً لا المعالج». والتالي: بالتعاون مع المطورين، كبّر مجمّع الخيوط على ⁦8⁩ vCPU وأعد الاختبار، واختبر التوسع الأفقي بمثيلات من ⁦4⁩ vCPU. فلو كان التوسع الأفقي خطياً لأعطت ثلاثة مثيلات ⁦3 × 480 = 1,440⁩ طلباً في الثانية كحد أقصى، وهذا يكفي ⁦1,125⁩، فتحتاج الخطة إلى أربعة مثيلات مع المثيل الاحتياطي (N+1)؛ لكن قِس ذلك أولاً، لأن مكوّناً مشتركاً قد يبلغ الثبات كما في المثال التطبيقي.

أسئلة شائعة

ما الفرق بين اختبار السعة واختبار الإجهاد؟

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

هل اختبار قابلية التوسع هو نفسه اختبار التوسع التلقائي؟

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

هل يمكنني اختبار السعة في بيئة أصغر ثم تكبير النتيجة؟

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

هل أحتاج إلى أداة خاصة لاختبار السعة؟

لا. أدوات الحمل التي مرّت في الدروس السابقة، مثل JMeter وk6 وGatling وLocust، تستطيع كلها رفع الحمل على خطوات. وما يختلف هو الخطة: حمل متدرج، والتشغيل نفسه مكرراً لكل تهيئة، ومراقبة جانب الخادم. وتسمّي وثائق Grafana k6 الاختبارَ الذي يرفع الحمل حتى يُخفق النظام اختبارَ نقطة الانهيار (Breakpoint Test)، وتذكر أن بعضهم يسمّيه اختبار السعة. وللحصول على السعة بالمعنى الذي يشرحه هذا الدرس، توقّف عند أول خطوة يسقط فيها أحد الأهداف؛ ويستطيع k6 فعل ذلك بعتبة (Threshold) مضبوطة على abortOnFail.

المراجع

تدرّب بأدوات متقن

ولّد مدخلات اختبار الأداء بتوزيعات واقعية: أزمنة التفكير، ومزيج الطلبات، وأحجام الحمولات، ومنحنيات التدرّج.

الأداء

شغّل قياس أداء صغيراً وآمناً على نقطة نهاية عامة (بعدد طلبات وتزامن محدودَين) واحصل على الإنتاجية ومئينيات زمن الاستجابة.

الأداء

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة