تطبيقي كان يعمل كالساعة… حتى زاره 100 مستخدم: كيف أنقذني ‘اختبار الحمل’ (Load Testing) من جحيم الأعطال؟

يا جماعة الخير، خليني أحكيلكم قصة صارت معي قبل كم سنة، قصة علّمتني درس ما بنساه. كنت وقتها شغال على تطبيق صغير، فكرته بسيطة وحلوة، وكنت مبسوط عليه كثير. شهور وأنا أبرمج وأصمم فيه، وكل شي كان ماشي “زي الساعة”. التطبيق سريع، الواجهات بتفتح بسرعة، وكل ميزة بضيفها بتشتغل من أول مرة. كنت أفرّجيه لأصحابي وقرايبي، والكل يحكيلي “ما شاء الله يا أبو عمر، شغل نظيف!”.

وصل يوم الإطلاق. بعد شوية تسويق بسيط على صفحات التواصل، بلشوا الناس يدخلوا على التطبيق. أول عشر مستخدمين… الأمور تمام. عشرين… ثلاثين… الوضع لسا تحت السيطرة. لما وصل العدد لقرابة الـ 100 مستخدم متزامن، بلشت المصايب. التطبيق صار أبطأ من السلحفاة، الصفحات بتحمّل بعد دهر، وبعدها… “Internal Server Error”. بلشت الإشعارات توصلني على إيميلي زي المطر، وقاعدة البيانات “ضربت” ورفضت تستقبل أي اتصال جديد. حسيت الدنيا بتلف فيي، وشغلي اللي تعبت عليه شهور قاعد بنهار قدام عيوني في دقائق. هذا كان جحيم الأعطال اللي بحكي عنه.

بعد ليلة طويلة من محاولات الإصلاح اليائسة، اكتشفت إن المشكلة ما كانت “bug” أو خطأ برمجي بالمعنى التقليدي. الكود كان صح، لكنه ما كان مصمم ليتحمل هذا “الحمل” المفاجئ. এখান থেকে (من هنا) تعلمت الدرس القاسي: التطبيق اللي بيشتغل كويس لمستخدم واحد، مش بالضرورة يشتغل كويس لمئة أو ألف. ومن يومها، صار “اختبار الحمل” أو الـ Load Testing جزء مقدس من شغلي، ما بستغني عنه أبدًا. واليوم، بدي أشارككم خبرتي هاي، عشان ما تقعوا بنفس الحفرة اللي وقعت فيها.

ما هو “اختبار الحمل” (Load Testing) يا أبو عمر؟ وليش هو مش رفاهية؟

ببساطة شديدة، تخيل إنك بنيت جسر. قبل ما تفتحه للسيارات، بتجيب أوزان ثقيلة وبتحطها عليه عشان تتأكد إنه بيتحمل، صح؟ هاد هو بالضبط اختبار الحمل للبرمجيات. هو نوع من “اختبارات الأداء” (Performance Testing) اللي بنقوم فيه بمحاكاة عدد كبير من المستخدمين الافتراضيين (Virtual Users) وهم بيستخدموا تطبيقك بنفس الوقت.

الهدف مش إننا “نكسر” التطبيق (هذا اسمه اختبار الإجهاد أو Stress Testing)، لكن الهدف هو نشوف كيف أداء التطبيق تحت ضغط متوقع. هل بصير بطيء؟ كم أقصى عدد من المستخدمين بيقدر يخدمهم بنفس الجودة؟ وين نقاط الضعف أو “عنق الزجاجة” (Bottlenecks) في نظامنا؟

باختصار، اختبار الحمل بجاوب على سؤال مهم: “هل تطبيقي جاهز للنجاح؟”. لأنه النجاح بيجي معاه مستخدمين كثار، والمستخدمين بيجيبوا ضغط. إذا أساساتك مش قوية، بيتك راح يوقع.

أنواع أخرى سريعة من اختبارات الأداء

  • Stress Testing (اختبار الإجهاد): هنا الهدف هو نزيد الضغط فوق المتوقع لحتى نشوف متى وكيف النظام بنهار.
  • Spike Testing (اختبار الذروة): محاكاة زيادة مفاجئة وكبيرة جدًا في عدد المستخدمين خلال فترة قصيرة جدًا.
  • Endurance Testing (اختبار التحمل): تشغيل حمل متوسط على النظام لفترة طويلة جدًا (ساعات أو أيام) لاكتشاف مشاكل مثل تسريب الذاكرة (Memory Leaks).

لكن اليوم، تركيزنا راح يكون على اختبار الحمل، لأنه هو خط الدفاع الأول والأهم.

كيف تبدأ رحلتك مع اختبار الحمل؟ (الخطوات العملية)

الموضوع مش معقد زي ما البعض بفكر. خلينا نمشي خطوة بخطوة.

الخطوة الأولى: تحديد الأهداف والسيناريوهات (مش كلشي لازم نختبره)

قبل ما تكتب سطر كود واحد، لازم تسأل حالك: “شو اللي بدي أختبره بالضبط؟”. لا تضيع وقتك في اختبار كل صفحة وزر في التطبيق. ركز على المسارات الحرجة (Critical User Journeys)، وهي العمليات اللي بيقوم فيها معظم المستخدمين واللي بتأثر بشكل مباشر على تجربتهم.

أمثلة على المسارات الحرجة:

  • في متجر إلكتروني: البحث عن منتج، إضافة المنتج للسلة، عملية الدفع.
  • في شبكة اجتماعية: تسجيل الدخول، تصفح الـ Feed، كتابة منشور جديد.
  • في نظام إدارة محتوى: الدخول للوحة التحكم، عرض المقالات.

بعد ما تحدد السيناريوهات، حدد أهداف أداء واضحة وقابلة للقياس. لا تقول “بدي التطبيق يكون سريع”. قول: “بدي متوسط زمن الاستجابة لصفحة المنتجات يكون أقل من 500ms تحت ضغط 200 مستخدم متزامن، وبنسبة أخطاء 0%”. الأرقام هي لغتنا كمطورين.

الخطوة الثانية: تجهيز بيئة الاختبار (اعزلها عن الإنتاج يا حبيب)

نصيحة من أخوك أبو عمر: إياك، ثم إياك، ثم إياك أن تجري اختبارات حمل ثقيلة على بيئة الإنتاج الحية (Production Server)! هذا مثل اختبار صلابة محرك سيارتك وهي ماشية على سرعة 120 كم/ساعة على الأوتوستراد. ممكن تسبب كارثة وتأثر على المستخدمين الحقيقيين.

الحل هو إنشاء بيئة اختبار (Staging/Testing Environment) تكون نسخة طبق الأصل عن بيئة الإنتاج قدر الإمكان:

  • نفس مواصفات العتاد: نفس عدد أنوية المعالج (CPU)، نفس حجم الذاكرة (RAM).
  • نفس البرمجيات: نفس إصدار نظام التشغيل، قاعدة البيانات، الـ Web Server.
  • نفس البيانات (تقريبًا): استخدم نسخة من بيانات الإنتاج (بعد إزالة أي معلومات حساسة طبعًا) عشان يكون الاختبار واقعي. اختبار قاعدة بيانات فاضية ما إله معنى.

الخطوة الثالثة: اختيار الأداة المناسبة (العدة الصح لشغل صح)

في أدوات كثيرة في السوق، بعضها قديم وقوي مثل Apache JMeter، وبعضها حديث وموجه للمطورين. أنا شخصيًا صرت أميل كثيرًا لأداة اسمها k6.

ليش k6؟

  • سهلة الاستخدام: بتكتب سكربتات الاختبار بلغة JavaScript، وهي لغة معظم المطورين بيعرفوها.
  • أداء عالي: مكتوبة بلغة Go، وهذا بيعطيها قدرة عالية على توليد ضغط كبير من جهاز واحد.
  • موجهة للمطورين: سهلة الإدماج مع أنظمة الـ CI/CD مثل GitHub Actions أو Jenkins.

مثال عملي: لنختبر “صفحة المنتجات” باستخدام k6

كلام نظري بكفي، خلينا نشوف شوية كود. تخيل عنا API Endpoint بجيب قائمة المنتجات: GET /api/products. بدنا نختبر كيف أداءه لما 100 مستخدم يطلبوه بنفس الوقت لمدة دقيقة.

كتابة السكريبت الأول (بسم الله)

أول شي، لازم تثبت k6 على جهازك (التعليمات موجودة على موقعهم الرسمي). بعدها، أنشئ ملف جديد اسمه test-products.js واكتب فيه الكود التالي:


import http from 'k6/http';
import { sleep, check } from 'k6';

// هاي هي إعدادات الاختبار اللي بنحدد فيها شكل الحمل
export const options = {
  // vus اختصار لـ Virtual Users (المستخدمين الافتراضيين)
  vus: 100,
  // مدة الاختبار الإجمالية
  duration: '60s',
};

// هذا هو السيناريو اللي راح ينفذه كل مستخدم افتراضي بشكل متكرر
export default function () {
  // الخطوة 1: إرسال طلب GET للـ API Endpoint
  const res = http.get('https://api.test.your-app.com/api/products');

  // الخطوة 2: التحقق من صحة الاستجابة (خطوة مهمة جدًا)
  // بدنا نتأكد إنه الطلب رجع بنجاح (status code 200)
  check(res, { 
    'status was 200': (r) => r.status == 200,
    'transaction time  r.timings.duration < 800,
  });

  // الخطوة 3: محاكاة تفكير المستخدم
  // المستخدم الحقيقي ما بضل يضغط F5 بدون توقف، لازم نحط فترة انتظار بسيطة
  sleep(1); // انتظر ثانية واحدة قبل تكرار الطلب
}

لتشغيل الاختبار، افتح الـ Terminal في نفس المجلد واكتب الأمر:

k6 run test-products.js

تحليل النتائج: كيف تقرأ الأرقام؟

بعد انتهاء الاختبار، k6 راح يعطيك ملخص جميل ومليان أرقام. لا تخاف منها، راح أشرحلك أهمها:


     ✓ status was 200
     ✓ transaction time < 800ms

     checks.........................: 100.00% ✓ 5824       ✗ 0
     data_received..................: 4.8 MB  80 kB/s
     data_sent......................: 524 kB  8.7 kB/s
     http_req_blocked...............: avg=1.26ms   min=2µs      med=5µs      max=68.12ms  p(90)=9µs      p(95)=11µs
     http_req_connecting............: avg=312.2µs  min=0s       med=0s       max=22.51ms  p(90)=0s       p(95)=0s
   ✓ http_req_duration..............: avg=250.46ms min=150.12ms med=230.8ms  max=750.2ms  p(90)=350.5ms  p(95)=480.7ms
       { expected_response:true }...: avg=250.46ms min=150.12ms med=230.8ms  max=750.2ms  p(90)=350.5ms  p(95)=480.7ms
   ✓ http_req_failed................: 0.00%   ✓ 0          ✗ 5824
     http_req_receiving.............: avg=112.3µs  min=19µs     med=80µs     max=6.2ms    p(90)=161µs    p(95)=215µs
     http_req_sending...............: avg=25.4µs   min=7µs      med=23µs     max=1.2ms    p(90)=38µs     p(95)=45µs
     http_req_tls_handshaking.......: avg=850.1µs  min=0s       med=0s       max=45.6ms   p(90)=0s       p(95)=0s
     http_req_waiting...............: avg=250.32ms min=150.04ms med=230.7ms  max=750.1ms  p(90)=350.3ms  p(95)=480.5ms
     http_reqs......................: 5824    97.05038/s
     iteration_duration.............: avg=1.02s    min=1.01s    med=1.02s    max=1.75s    p(90)=1.03s    p(95)=1.04s
     iterations.....................: 5824    97.05038/s
     vus............................: 100     min=100      max=100
     vus_max........................: 100     min=100      max=100

أهم مؤشرين لازم تركز عليهم:

  1. http_req_failed: نسبة الطلبات الفاشلة. هدفك دائمًا يكون هذا الرقم 0.00%. إذا شفت أي نسبة فشل، معناها النظام بدأ ينهار تحت الضغط.
  2. http_req_duration: هذا هو وقت استجابة الطلب. ركز على هاي القيم:
    • avg: متوسط وقت الاستجابة. رقم جيد للمتابعة، لكنه خداع أحيانًا.
    • p(95): أهم رقم في رأيي. هاي القيمة معناها “95% من الطلبات تمت في وقت أقل من هذا الرقم”. في مثالنا، p(95)=480.7ms يعني 95% من المستخدمين حصلوا على استجابة في أقل من نصف ثانية، وهذا ممتاز! ليش هو أهم من المتوسط؟ لأنه المتوسط ممكن يتأثر بكم طلب سريع جدًا، لكن p(95) بيعطيك صورة عن تجربة معظم المستخدمين، مش بس المتوسط الحسابي.

إذا كانت هاي الأرقام ضمن الأهداف اللي حددتها في الخطوة الأولى، فمبروك! الـ Endpoint تبعك قوي. إذا كانت الأرقام سيئة (مثلًا p(95) كان 3000ms)، فهنا يبدأ العمل الحقيقي: تحليل “عنق الزجاجة”.

نصائح من “كيس” أبو عمر (خلاصة تجارب)

  • ابدأ بسيطًا ثم تعقّد: لا تبدأ الاختبار بـ 1000 مستخدم. ابدأ بـ 10، ثم 50، ثم 100، 200 وهكذا. راقب كيف تتغير الأرقام مع زيادة الحمل. هذا يساعدك تكتشف نقطة الانهيار بدقة.
  • الاختبار ليس مرة واحدة: أفضل ممارسة هي دمج اختبارات الحمل في عملية الـ CI/CD. شغل اختبار بسيط مع كل عملية دمج (merge) للكود، واختبار أثقل كل ليلة. هيك بتكتشف مشاكل الأداء أول بأول، مش ليلة الإطلاق.
  • راقب النظام أثناء الاختبار: لا تكتفي بالنظر لنتائج k6. افتح شاشات مراقبة (Monitoring) للسيرفر نفسه أثناء الاختبار. راقب استهلاك الـ CPU، الـ Memory، الـ I/O تبع القرص الصلب، واستعلامات قاعدة البيانات البطيئة (Slow Queries). الأدوات مثل htop, Prometheus, Grafana, أو خدمات مثل New Relic و Datadog هي أصدقاؤك هنا.
  • اعرف عنق الزجاجة (The Bottleneck): هل المشكلة في استعلام قاعدة بيانات غير محسن (Missing Index)؟ هل هي مكتبة خارجية بطيئة؟ هل الـ Web Server إعداداته غير صحيحة؟ هل تحتاج لعمل Caching؟ الهدف من الاختبار هو إيجاد هذا “العنق” وتوسيعه.

الخلاصة: لا تنتظر الكارثة لتبني سفينتك 🚢

يا جماعة، القصة اللي حكيتها في البداية كانت مؤلمة، لكنها كانت أفضل درس تعلمته في مسيرتي. البرمجة مش بس كتابة كود شغال، البرمجة هي بناء أنظمة قوية وموثوقة تقدر تخدم المستخدمين في أحسن الظروف وأسوئها.

اختبار الحمل مش رفاهية أو خطوة إضافية. هو بوليصة تأمين لتطبيقك، هو اللي بيخليك تنام مرتاح بالليل وأنت عارف إن تطبيقك جاهز يستقبل ضيوفه الكرام، سواء كانوا عشرة أو عشرة آلاف.

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

الله يوفقكم في مشاريعكم، ويبعد عنكم جحيم الأعطال! 🙏

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

التوسع والأداء العالي والأحمال

خادم واحد كان يتحمل كل العبء: كيف أنقذتني ‘موازنة الأحمال’ (Load Balancing) من جحيم نقطة الفشل الواحدة؟

أشارككم قصة حقيقية عن انهيار تطبيق بسبب الاعتماد على خادم واحد، وكيف كانت تقنية "موازنة الأحمال" (Load Balancing) هي طوق النجاة. سنتعمق في مفهومها، خوارزمياتها،...

29 مارس، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

عمليات التحقق كانت تغرق في الأوراق: كيف أنقذني ‘التعرف الآلي على العملاء’ (eKYC) من جحيم الغرامات التنظيمية؟

أشارككم قصتي مع أكوام الوثائق التي كادت أن تدمر شركة ناشئة، وكيف كانت تقنية التعرف الآلي على العملاء (eKYC) والذكاء الاصطناعي طوق النجاة. هذه المقالة...

29 مارس، 2026 قراءة المزيد
أدوات وانتاجية

إعداد فريقي كان يستغرق أيامًا: كيف أنقذتني ‘حاويات التطوير’ (Dev Containers) من جحيم التضارب بين البيئات؟

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

29 مارس، 2026 قراءة المزيد
أتمتة العمليات

بيئات العمل كانت تتغير من تلقاء نفسها: كيف أنقذتني ‘البنية التحتية كشفرة’ (IaC) من جحيم التكوينات الشبحية؟

أشارككم قصة حقيقية عن ليلة كابوسية قضيتها في تصحيح خطأ غامض في خوادم الإنتاج، وكيف كانت "البنية التحتية كشفرة" (IaC) هي المنقذ. اكتشفوا معي كيف...

29 مارس، 2026 قراءة المزيد
​معمارية البرمجيات

خدماتي كانت مقيدة ببعضها البعض: كيف أنقذتني ‘المعمارية القائمة على الأحداث’ (EDA) من جحيم التشابك الخانق؟

أشارككم قصة حقيقية من مسيرتي كمبرمج، وكيف أنقذتني المعمارية القائمة على الأحداث (EDA) من نظام متشابك ومعقد. سنغوص في تفاصيل هذه المعمارية، وكيف يمكنها فك...

29 مارس، 2026 قراءة المزيد
تسويق رقمي

حملاتي كانت تخاطب الجميع ولا أحد: كيف أنقذني التخصيص المدعوم بالذكاء الاصطناعي من جحيم معدلات التحويل المنخفضة؟

كنت أظن أن التسويق للجميع هو الحل الأمثل، حتى رأيت معدلات التحويل تنهار أمامي. في هذه المقالة، أشارككم قصتي مع التخصيص (Personalization) وكيف غير الذكاء...

29 مارس، 2026 قراءة المزيد
البودكاست