معظم الشركات التي أعمل معها في الكويت والإمارات لا تفكر في تحديد معدل الطلبات إلا عندما يأتيها الشرر — أي عندما ينهار الـ API ويتوقف كل شيء. وبحلول الوقت الذي تحاول فيه الحل، تكون قد خسرت آلاف الريالات بالفعل.
المشكلة أن معظم المطورين الشباب يركزون على بناء الميزات وينسون أن أي API ناجح سيواجه يوماً ما طلباً غير متوقع — هجمة DDoS، مستخدم يترك loop في الكود، أو حتى مشروع تسويقي تم إطلاقه بدون تنسيق مع الفريق التقني. والنتيجة أن الخادم ينهار.
لماذا تحديد المعدل ليس خياراً فاخراً؟
في دراسة نشرتها Cloudflare عام 2024، وجدوا أن 72% من هجمات DDoS تستهدف API وخدمات الويب مباشرة. لكن الخبر الجيد أن 63% من هذه الهجمات كان يمكن إيقافها بـ rate limiting بسيط.
من تجربتي المباشرة في إدارة مشاريع خليجية، رأيت خادماً واحداً انهار بـ 40 دقيقة لأن عميل بريطاني نسي إيقاف script اختبار. التكلفة؟ 8 ساعات downtime، آلاف العملاء غير قادرين على الوصول للخدمة، وقيمة سمعة فقدت. كل ذلك كان يمكن منعه بـ 10 دقائق من الكود.
تحديد المعدل ليس حول منع المهاجمين فقط — إنه حول ضمان أن خادمك يبقى حياً ومستجيباً لعملائك الشرعيين دائماً. بصراحة، إذا كان API الخاص بك تحت أي ضغط على الإطلاق، فأنت بحاجة إلى هذا.
دلو الرموز: الحل الذكي والمرن
تخيل أن لديك دلو يحتوي على 100 قطعة نقود. كل طلب يأتي يأخذ قطعة نقود واحدة. كل ثانية، يُضاف 50 قطعة جديدة إلى الدلو (بحد أقصى 100). إذا جاء طلب والدلو فارغ، فإنك ترفضه. هذا هو Token Bucket بكل بساطة.
ملاحظة من الميدان
في مشروع سوشيال ميديا مصري، طبقنا Token Bucket ووجدنا أن 85% من الطلبات المرفوضة كانت من bots وmultiple connections من حسابات مزيفة. الـ 15% الباقية كانت أخطاء برمجية شرعية من العملاء — وتلك كانت علامة لنا لتحسين الأداء، لا لزيادة الحد.
المزايا الحقيقية لـ Token Bucket:
- مرونة قصيرة الأمد: إذا كان لديك 100 طلب في الثانية كحد، يمكن للعميل إرسال 150 طلب بسرعة عالية في الثانية الأولى، ثم ينتظر الثانية الثانية. هذا مفيد للعمليات البرمجية الحقيقية التي تحتاج للمرونة.
- بسيط في التطبيق: خوارزمية مستقيمة، لا تحتاج إلى متغيرات معقدة أو ذاكرة كبيرة.
- قابل للتخصيص الدقيق: يمكنك ضبط سعر الملء (capacity) ومعدل الإضافة (refill rate) بسهولة بدون إعادة بناء كل شيء.
لكن التحدي الحقيقي يأتي عندما تحتاج إلى تطبيقه على نطاق واسع. إذا كان لديك 10 آلاف عميل، فأنت تحتاج إلى 10 آلاف دلو منفصل. في الأنظمة الموزعة (distributed systems)، هذا يعني تخزين حالة كل دلو — والقراءات والكتابات على قاعدة البيانات أو Redis تصبح قطاع الاختناق.
النافذة المنزلقة: البديل الصارم والأكثر أماناً
تخيل إطار زمني متحرك مدته دقيقة واحدة. في كل لحظة، تنظر فقط إلى الطلبات التي حدثت في آخر دقيقة. إذا كان هناك أكثر من 100 طلب في آخر دقيقة، فأنت ترفض الطلب الجديد. هذا هو Sliding Window.
بصراحة، هذا أقل مرونة من Token Bucket. إذا أرسل العميل 150 طلب في أول ثانية، فسيتم رفض 50 منها فوراً. لكن هذا بالضبط ما قد تريده إذا كنت تريد حماية حقيقية.
Token Bucket
الأفضل لـ: APIs التي تحتاج مرونة، مثل خدمات الدفع والعمليات البطيئة. العملاء الشرعيون قد يأتون بـ burst ثقيل لفترة قصيرة ثم ينتظرون.
التحدي: معقد في الأنظمة الموزعة لأنك تحتاج لتتبع حالة الدلو لكل عميل.
Sliding Window
الأفضل لـ: APIs الحساسة والعامة، مثل APIs البحث وAPIs القراءة فقط. تريد حماية قوية من الهجمات المفاجئة.
التحدي: قد يرفض طلبات شرعية إذا جاء العميل بـ burst سريع، حتى لو كان معدله الكلي تحت الحد.
Sliding Window with Quota
الأفضل لـ: Hybrid approach — تتبع طلبات الدقيقة الماضية بدقة عالية مع السماح ببعض المرونة عند الحدود.
التحدي: يحتاج تنفيذاً ذكياً. إذا أسأت الحساب، قد تسمح بـ 2x من الحد الكلي.
الخطوات العملية: كيف تطبقها الآن
سأكون صريحاً: معظم المشاريع الخليجية الناشئة تبدأ بـ Token Bucket لأنه أبسط. ثم عندما تنمو، تنتقل إلى Sliding Window أو نموذج مختلط.
إذا كنت تستخدم Laravel (وأعتقد أنك تستخدمه إذا كنت في الكويت)، هناك middleware جاهز:
composer require laravel/tinker والحزم مثل laravel-rate-limit موجودة وقابلة للاستخدام الفوري. لكن نصيحتي: اكتب نسختك الخاصة. الخوارزميات بسيطة، والفهم العميق أهم من الاعتماد على مكتبة.
إذا كنت على Node.js، جرب express-rate-limit مع Redis كـ store. هذا يعطيك سرعة وتوزيع.
المفتاح: لا تخزّن الحالة في الذاكرة فقط. إذا أعدت تشغيل الخادم، ستفقد جميع الحدود. استخدم Redis أو قاعدة بيانات خفيفة، حتى لو كنت تعتقد أنك صغير جداً.
التحذيرات الصريحة التي رأيتها بنفسي
رأيت شركة سعودية تطبق rate limiting بدون إخطار العميل. النتيجة؟ آلاف من تقارير الأخطاء من المطورين الثالثين الذين اعتقدوا أن API مكسور. الدرس: إذا رفضت طلباً، أرسل header واضح مثل X-RateLimit-Remaining: 0 و Retry-After: 30. أخبر العميل بالضبط ماذا يحدث.
أيضاً، احذر من تطبيق حدود قاسية جداً. رأيت API قطري حدّد حد 10 طلبات في الدقيقة لقراءة البيانات. نعم، 10 فقط. حتى طلبات الصفحة الواحدة كانت تستدعي API 15 مرة. النتيجة: عملاء غاضبون وتقييمات سيئة.
والنقطة الأخيرة: لا تطبق نفس الحد على جميع العملاء. العملاء المدفوعون يستحقون حد أعلى. والعملاء الجدد قد يحتاجون وقتاً للتعلم. استخدم tiered limits بناءً على الخطة أو السمعة.
الخلاصة: أي واحد تختار؟
إذا كنت تبني API جديد، ابدأ بـ Token Bucket. إنه أبسط وأسهل للفهم والتوسع. عندما تبدأ في رؤية هجمات منظمة أو طلبات غير متوقعة، انتقل إلى Sliding Window أو نموذج مختلط.
لكن الحقيقة الأهم هي هذه: تحديد معدل الطلبات ليس شيئاً اختياري. إنه ضرورة. وكلما بدأت مبكراً، كلما نمت بثقة أكبر.