تحديد معدل الطلبات في Node.js: دليل كامل لحماية API وإدارة الحمل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

تحديد معدل الطلبات في Node.js: حماية API من الأحمال الزائدة والمهاجمين

\n\n

تحديد معدل الطلبات (Rate limiting) هو آلية بالغة الأهمية لأي تطبيق ويب يعمل بـ Node.js. فهو يسمح لك بالتحكم في عدد الطلبات التي يمكن للعميل إرسالها إلى الخادم خلال فترة زمنية محددة. بدون تحديد معدل الطلبات، يكون API الخاص بك عرضة لهجمات DDoS والأحمال الزائدة العشوائية والاستهلاك المفرط للموارد.

\n\n

لماذا نحتاج إلى تحديد معدل الطلبات؟

\n
    \n
  • الحماية من هجمات القوة العمياء: يمنع محاولات تسجيل الدخول المتكررة.
  • \n
  • منع هجمات DDoS: يحد من تأثير هجمات حجب الخدمة.
  • \n
  • توزيع عادل للموارد: يضمن وصولاً متساوياً لجميع المستخدمين.
  • \n
  • توفير التكاليف: يقلل الحمل على الخوادم وقواعد البيانات.
  • \n
  • الامتثال لاتفاقيات مستوى الخدمة (SLA): تنفيذ اتفاقيات مستوى الخدمة.
  • \n
\n\n

الخوارزميات الأساسية لتحديد معدل الطلبات

\n

هناك عدة طرق لتنفيذ تحديد السرعة. دعنا نستعرض الأكثر شيوعاً:

\n\n

1. النافذة المنزلقة (Sliding Window)

\n

الخوارزمية الأكثر انتشاراً. يتم تجميع الطلبات في نوافذ زمنية (مثل دقيقة واحدة). إذا تجاوز عدد الطلبات الحد المسموح، يتم رفض الطلبات التالية حتى بداية نافذة جديدة.

\n\n

2. دلو الرموز (Token Bucket)

\n

"دلو" افتراضي يحتوي على رموز. يستهلك كل طلب رمزاً واحداً. يتم تجديد الرموز بمعدل ثابت. إذا كان الدلو فارغاً، يتم رفض الطلب.

\n\n

3. الدلو المتسرب (Leaky Bucket)

\n

تدخل الطلبات إلى قائمة انتظار وتتم معالجتها بمعدل ثابت. إذا امتلأت قائمة الانتظار، يتم تجاهل الطلبات.

\n\n

مكتبات لتحديد معدل الطلبات في Node.js

\n\n

1. express-rate-limit

\n

المكتبة الأكثر شيوعاً لـ Express.js. سهلة الاستخدام وقابلة للتخصيص.

\n\n
const rateLimit = require('express-rate-limit');\n\n// إنشاء middleware لتقييد الطلبات\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 دقيقة\n  max: 100, // الحد الأقصى 100 طلب لكل نافذة\n  message: 'عدد كبير جداً من الطلبات، حاول مرة أخرى لاحقاً.',\n  standardHeaders: true, // إرجاع رؤوس RateLimit-*\n  legacyHeaders: false, // تعطيل رؤوس X-RateLimit-*\n});\n\n// تطبيق على جميع المسارات\napp.use(limiter);\n\n// أو فقط على مسار معين\napp.use('/api/login', limiter);\n
\n\n

2. bottleneck

\n

مكتبة متعددة الاستخدامات تعمل مع أي عمليات غير متزامنة. تدعم خوارزميات Token Bucket و Leaky Bucket.

\n\n
const Bottleneck = require('bottleneck');\n\n// إنشاء محدد: 5 طلبات في الثانية\nconst limiter = new Bottleneck({\n  minTime: 200, // 200 مللي ثانية بين الطلبات\n  maxConcurrent: 5, // الحد الأقصى 5 طلبات متزامنة\n  reservoir: 100, // العدد الأولي للرموز\n  reservoirRefreshAmount: 100,\n  reservoirRefreshInterval: 60 * 1000, // التجديد كل دقيقة\n});\n\n// تغليف الدالة في المحدد\nasync function fetchData(url) {\n  const response = await fetch(url);\n  return response.json();\n}\n\nconst limitedFetch = limiter.wrap(fetchData);\n\n// الاستخدام\nconst data = await limitedFetch('https://api.example.com/data');\n
\n\n

3. rate-limiter-flexible

\n

مكتبة مرنة مع دعم Redis و MongoDB و Memcached وغيرها من المخازن. مثالية للأنظمة الموزعة.

\n\n
const { RateLimiterRedis } = require('rate-limiter-flexible');\nconst Redis = require('ioredis');\n\nconst redisClient = new Redis();\n\nconst rateLimiter = new RateLimiterRedis({\n  storeClient: redisClient,\n  keyPrefix: 'middleware',\n  points: 10, // 10 طلبات\n  duration: 1, // خلال ثانية واحدة\n});\n\napp.use(async (req, res, next) => {\n  try {\n    await rateLimiter.consume(req.ip);\n    next();\n  } catch (rejRes) {\n    res.status(429).send('عدد كبير جداً من الطلبات');\n  }\n});\n
                
    
    

توصيات