תארו לעצמכם שה-API שלכם קורס תחת עומס, עם אלפי בקשות מכתובת IP אחת בלוגים. באחד הפרויקטים שלנו, שירות צד שלישי נתקע בלולאה, ושלח 10,000 בקשות בדקה. ללא הגבלת קצב (Rate Limiting), זה הפיל את מסד הנתונים וגרם ל-4 שעות של השבתה. פרסנו מגבלות גם ברמת Nginx וגם ברמת האפליקציה—הבעיה לא חזרה. מקרים כאלה הם הלחם היומיומי שלנו.
אנו מיישמים הגבלת קצב עבור APIs של יישומי אינטרנט על כל טכנולוגיה—מ-Laravel ועד NestJS—עם backend של Redis, מגבלות מבוססות שכבות, וכותרת תגובה מתאימה. להלן גישות מוכחות בקרב שמסייעות לכם להימנע מהשבתות ולהגן על התשתית שלכם.
כיצד לבחור אלגוריתם להגבלת קצב
הבחירה תלויה בתבנית התעבורה. Sliding Window ממצע בקשות על פני חלון נע, ומונע את הפגיעות של Fixed Window: כאשר המונה מתאפס כל N שניות, לקוח יכול לשלוח 100 בקשות בסוף החלון ו-100 בתחילת החלון הבא—למעשה 200 בשנייה. Sliding Window מונע זאת. Token Bucket צובר אסימונים בקצב מילוי, ומאפשר פרצי עומס עד לגודל הדלי—אידיאלי לאינטגרציות עם תעבורה לא סדירה. Leaky Bucket מעמיד בקשות בתור עם קצב ניקוז קבוע, ומספק עומס חלק ביותר אך עלול לגרום לעיכובים.
| אלגוריתם | דיוק | הגנה מפני פרצים | מורכבות יישום | תרחיש מומלץ |
|---|---|---|---|---|
| Fixed Window | נמוך | לא | נמוכה | תוכניות שכבות פשוטות |
| Sliding Window | גבוה | כן | בינונית | APIs לשימוש כללי |
| Token Bucket | בינוני | כן | בינונית | תעבורת פרצים של שותפים |
| Leaky Bucket | גבוה | לא | גבוהה | מערכות זמן אמת |
עבור רוב יישומי האינטרנט, Sliding Window עם Redis הוא אופטימלי. הוא מספק ויסות אחיד ללא קפיצות בקצוות החלון. אם ה-API שלכם מתמודד עם תעבורת פרצים (למשל, מאינטגרציות של שותפים), בחרו ב-Token Bucket. עבור מערכות זמן אמת עם זרם קבוע, Leaky Bucket הוא הטוב ביותר.
למה לשלב הגבלת קצב ב-Nginx וברמת האפליקציה?
Nginx משמש כקו ההגנה הראשון: הוא יכול לחסום חריגות ברורות (למשל, יותר מ-1000 בקשות בשנייה מכתובת IP אחת) ברמת השרת, מבלי להעמיס על האפליקציה. לאחר מכן, האפליקציה מספקת מגבלות גמישות לפי משתמש ושכבה. הגנה דו-שכבתית זו יעילה יותר מכל יישום חד-שכבתי. ניתן להגדיר את Nginx עם מודול limit_req להגנה כללית, ולהגדיר חוקים מדויקים יותר באפליקציה.
יישום ב-Laravel וב-NestJS
Laravel — באמצעות Throttle middleware ו-RateLimiter:
// app/Providers/RouteServiceProvider.php
RateLimiter::for('api', function (Request $request) {
$user = $request->user();
if (!$user) return Limit::perMinute(30)->by($request->ip());
return match($user->plan) {
'enterprise' => Limit::perMinute(1000)->by($user->id),
'pro' => Limit::perMinute(300)->by($user->id),
default => Limit::perMinute(60)->by($user->id),
};
});
Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () {
Route::apiResource('articles', ArticleController::class);
});
NestJS — באמצעות מודול @nestjs/throttler עם אחסון Redis:
import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
ThrottlerModule.forRoot({
throttlers: [
{ name: 'short', ttl: 1000, limit: 10 },
{ name: 'medium', ttl: 60000, limit: 300 },
{ name: 'long', ttl: 3600000, limit: 5000 },
],
storage: new ThrottlerStorageRedisService(redisClient),
});
| היבט | Laravel | NestJS | Nginx |
|---|---|---|---|
| גמישות מגבלות | גבוהה (לפי משתמש, תוכנית) | גבוהה (לפי קבוצת נתיבים) | נמוכה (רק לפי IP) |
| ביצועים | בינוניים (PHP) | גבוהים (Node.js) | מקסימליים (C) |
| אחסון מרכזי | Redis | Redis | לא (או מודול חיצוני) |
| כותרות Retry-After | אוטומטי | אוטומטי | ידני |
הגבלת קצב מבוזרת עם סקריפט Lua
עבור יישומים מרובי שרתים, אנו משתמשים ב-Redis מרכזי ומונה Lua אטומי:
-- sliding_window.lua
local key = KEYS[1]
local now = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local limit = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)
if count < limit then
redis.call('ZADD', key, now, now .. math.random())
redis.call('EXPIRE', key, window / 1000)
return 1
end
return 0
סקריפט זה מבטיח אטומיות ועובד בארכיטקטורות מבוזרות. אנו משתמשים בו בפרויקטים בעלי עומס גבוה.
אסטרטגיות עקיפה: מה לא להגביל
חלק מהבקשות חייבות לעקוף מגבלות: שירותים פנימיים (רשימת IP מותרת), נקודות קצה של webhook, בדיקות בריאות // app/Providers/RouteServiceProvider.php RateLimiter::for('api', function (Request $request) { $user = $request->user(); if (!$user) return Limit::perMinute(30)->by($request->ip()); return match($user->plan) { 'enterprise' => Limit::perMinute(1000)->by($user->id), 'pro' => Limit::perMinute(300)->by($user->id), default => Limit::perMinute(60)->by($user->id), }; }); Route::middleware(['auth:sanctum', 'throttle:api'])->group(function () { Route::apiResource('articles', ArticleController::class); }); . יש ליישם זאת באמצעות תנאי ב-RateLimiter:
RateLimiter::for('api', function (Request $request) {
if ($request->ip() === config('services.internal_ip')) {
return Limit::none();
}
// ...
}); טעויות נפוצות ביישום הגבלת קצב
ב-70% מהפרויקטים שבדקנו, נעשה שימוש ב-Fixed Window ללא התחשבות בפרצים—מה שמאפשר ללקוחות לעקוף את המגבלה. עוד 20% מתעלמים מכותרות import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler'; import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis'; ThrottlerModule.forRoot({ throttlers: [ { name: 'short', ttl: 1000, limit: 10 }, { name: 'medium', ttl: 60000, limit: 300 }, { name: 'long', ttl: 3600000, limit: 5000 }, ], storage: new ThrottlerStorageRedisService(redisClient), }); , ומשאירים את הלקוחות ללא ידיעה מתי לנסות שוב. הגבלת בדיקות בריאות גורמת להתראות ניטור שגויות. התעלמות מאחסון מבוזר מובילה למונים לא עקביים בין שרתים.
מה כולל יישום סוהר
- ניתוח הארכיטקטורה הנוכחית ופרופיל התעבורה.
- בחירת אלגוריתם (אנו ממליצים על Sliding Window + Redis).
- הגדרת מגבלות לפי נקודת קצה ושכבה.
- אינטגרציה עם Nginx כקו הגנה ראשון.
- הוספת כותרות
-- sliding_window.lua local key = KEYS[1] local now = tonumber(ARGV[1]) local window = tonumber(ARGV[2]) local limit = tonumber(ARGV[3]) redis.call('ZREMRANGEBYSCORE', key, 0, now - window) local count = redis.call('ZCARD', key) if count < limit then redis.call('ZADD', key, now, now .. math.random()) redis.call('EXPIRE', key, window / 1000) return 1 end return 0ו-/health. - ניטור תגובות 429 (Grafana + התראות).
- תיעוד והדרכת צוות.
לוח זמנים
יישום בסיסי עם Redis ו-Sliding Window: 1–2 ימים. מורחב עם Nginx, סקריפטים של Lua וניטור: 3–4 ימים. העלות מחושבת באופן אישי לאחר ניתוח הפרויקט שלכם. אנו מעריכים את הפרויקט שלכם תוך יום אחד—צרו קשר לייעוץ. הזמינו יישום הגבלת קצב, וה-API שלכם יעמוד בכל עומס.
יישמנו הגבלת קצב עבור 20+ פרויקטים ברמות מורכבות שונות. היו סמוכים ובטוחים, לאחר הפריסה שלנו, תשכחו מבעיות עומס.







