تحديد معدل الطلبات في Node.js: حماية API من الأحمال الزائدة والمهاجمين
\n\nتحديد معدل الطلبات (Rate limiting) هو آلية بالغة الأهمية لأي تطبيق ويب يعمل بـ Node.js. فهو يسمح لك بالتحكم في عدد الطلبات التي يمكن للعميل إرسالها إلى الخادم خلال فترة زمنية محددة. بدون تحديد معدل الطلبات، يكون API الخاص بك عرضة لهجمات DDoS والأحمال الزائدة العشوائية والاستهلاك المفرط للموارد.
\n\nلماذا نحتاج إلى تحديد معدل الطلبات؟
\n- \n
- الحماية من هجمات القوة العمياء: يمنع محاولات تسجيل الدخول المتكررة. \n
- منع هجمات DDoS: يحد من تأثير هجمات حجب الخدمة. \n
- توزيع عادل للموارد: يضمن وصولاً متساوياً لجميع المستخدمين. \n
- توفير التكاليف: يقلل الحمل على الخوادم وقواعد البيانات. \n
- الامتثال لاتفاقيات مستوى الخدمة (SLA): تنفيذ اتفاقيات مستوى الخدمة. \n
الخوارزميات الأساسية لتحديد معدل الطلبات
\nهناك عدة طرق لتنفيذ تحديد السرعة. دعنا نستعرض الأكثر شيوعاً:
\n\n1. النافذة المنزلقة (Sliding Window)
\nالخوارزمية الأكثر انتشاراً. يتم تجميع الطلبات في نوافذ زمنية (مثل دقيقة واحدة). إذا تجاوز عدد الطلبات الحد المسموح، يتم رفض الطلبات التالية حتى بداية نافذة جديدة.
\n\n2. دلو الرموز (Token Bucket)
\n"دلو" افتراضي يحتوي على رموز. يستهلك كل طلب رمزاً واحداً. يتم تجديد الرموز بمعدل ثابت. إذا كان الدلو فارغاً، يتم رفض الطلب.
\n\n3. الدلو المتسرب (Leaky Bucket)
\nتدخل الطلبات إلى قائمة انتظار وتتم معالجتها بمعدل ثابت. إذا امتلأت قائمة الانتظار، يتم تجاهل الطلبات.
\n\nمكتبات لتحديد معدل الطلبات في Node.js
\n\n1. express-rate-limit
\nالمكتبة الأكثر شيوعاً لـ Express.js. سهلة الاستخدام وقابلة للتخصيص.
\n\nconst 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\n2. bottleneck
\nمكتبة متعددة الاستخدامات تعمل مع أي عمليات غير متزامنة. تدعم خوارزميات Token Bucket و Leaky Bucket.
\n\nconst 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\n3. rate-limiter-flexible
\nمكتبة مرنة مع دعم Redis و MongoDB و Memcached وغيرها من المخازن. مثالية للأنظمة الموزعة.
\n\nconst { 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
أيضاً في المكتبة
توصيات