همانطور که معماریهای مبتنی بر API به ستون فقرات تجربیات دیجیتال مدرن تبدیل میشوند، ایمنسازی این نقاط پایانی در برابر سوءاستفاده، حملات رباتها و افزایشهای ناگهانی ترافیک دیگر یک انتخاب نیست، بلکه حیاتی است. یکی از موثرترین ابزارها در جعبه ابزار مهندسان، محدودیت نرخ (Rate Limiting) است. با این حال، انتخاب الگوریتم مناسب میتواند تأثیر قابل توجهی بر عملکرد سیستم و تجربه کاربری داشته باشد. در این پست، ما به عمق دو استراتژی رایجتر میرویم: الگوریتم سطل توکن و رویکرد لاگ پنجره لغزان.
چرا محدودیت نرخ مهم است
قبل از انتخاب یک الگوریتم، درک تهدیداتی که در حال کاهش آنها هستیم ضروری است. محدودیت نرخ سه هدف اصلی دارد: محافظت از خدمات بکاند در برابر بار بیش از حد، جلوگیری از سوءاستفادههای مخرب مانند حملات brute-force و اطمینان از استفاده عادلانه بین مستأجران در محیطهای چند مستأجره. بدون این کنترلها، یک کلاینت سرکش میتواند تمام منابع موجود را مصرف کند و منجر به رد خدمات (DoS) برای کاربران قانونی شود.
الگوریتم سطل توکن: پر از کارایی
الگوریتم سطل توکن به دلیل سادگی و توانایی آن در مدیریت ترافیکهای ناگهانی به صورت روان، به طور گستردهای مورد پسند است. تصور کنید یک سطل با ظرفیت ثابت وجود دارد. توکنها با نرخ ثابت به سطل اضافه میشوند. هر درخواست ورودی یک توکن مصرف میکند. اگر سطل خالی باشد، درخواست رد یا به تعویق میافتد.
ویژگیهای کلیدی
- مدیریت ترافیک ناگهانی: برخلاف شمارندههای پنجره ثابت خشک، سطلهای توکن اجازه میدهند ترافیک کوتاه مدت تا ظرفیت سطل رخ دهد.
- نرخ روان: در طول زمان، میانگین عبور داده با نرخ شارژ مجدد مطابقت دارد.
- سربار کم: این الگوریتم به حافظه کمی نیاز دارد که آن را برای سیستمهای توزیع شده که به اشتراکگذاری حالت در آنها پرهزینه است، ایدهآل میکند.
مفهوم پیادهسازی
هنگام پیادهسازی این الگوریتم در یک دروازه API مانند NGINX یا Kong، معمولاً نرخ را پیکربندی میکنید که تعریف میکند توکنها چقدر سریع شارژ میشوند. در زیر یک قطعه کد پیکربندی مفهومی برای یک دروازه مبتنی بر Lua آورده شده است:
-- پیکربندی سطل توکن
local token_bucket = require "resty.token_bucket"
-- تعریف ظرفیت سطل و نرخ شارژ مجدد
local bucket = token_bucket:new({
capacity = 100, -- حداکثر اندازه ترافیک ناگهانی
refill_rate = 10, -- توکن در ثانیه
key = "client_ip" -- محدودیت نرخ بر اساس IP
})
if bucket:consume() then
-- درخواست مجاز است
return ngx.HTTP_OK
else
-- محدودیت نرخ تجاوز کرده است
return ngx.HTTP_TOO_MANY_REQUESTS
end
لاگ پنجره لغزان: دقت در ردیابی
در حالی که سطل توکن برای صاف کردن ترافیک عالی است، گاهی اوقات در زمان تغییرات سریع در حجم درخواستها میتواند بیش از حد ملایم یا نادرست باشد. لاگ پنجره لغزان (که اغلب به عنوان شمارنده پنجره لغزان نیز شناخته میشود) اندازهگیری دقیقتری از نرخهای درخواست در یک دوره زمانی در حال چرخش ارائه میدهد.
نحوه عملکرد
این الگوریتم لیستی (لاگ) از مهرهای زمانی برای هر درخواست در پنجره فعلی را حفظ میکند. وقتی یک درخواست جدید میرسد، سیستم لاگ را بررسی میکند، مهرهای زمانی قدیمیتر از اندازه پنجره (مثلاً ۶۰ ثانیه گذشته) را حذف میکند و ورودیهای باقیمانده را میشمارد. اگر تعداد از حد مجاز فراتر رود، درخواست رد میشود.
تبادلات
عیب اصلی لاگ پنجره لغزان مصرف حافظه است. ذخیره یک مهر زمانی برای هر درخواست میتواند در حجمهای ترافیکی بالا پرهزینه شود. با این حال، این روش از "اثر مرزی" که در شمارندههای پنجره ثابت دیده میشود، جلوگیری میکند، جایی که افزایش ترافیک در ابتدای یک پنجره جدید میتواند بکاند را دو برابر بیشتر از معمول تحت فشار قرار دهد.
انتخاب استراتژی مناسب
پس کدام یک را باید انتخاب کنید؟ اگر API شما نیاز به جذب افزایشهای ناگهانی ترافیک از کمپینهای بازاریابی یا رویدادهای وایرال دارد، سطل توکن به دلیل انعطافپذیری و ردپای حافظه کم، معمولاً انتخاب بهتری است. در مقابل، اگر در حال ساخت یک سیستم صورتحساب سختگیرانه یا یک API با سقفهای سخت هستید که در آن هر درخواست به دقت مهم است، پنجره لغزان کنترل دانهدانه لازم را برای اعمال دقیق محدودیتها فراهم میکند.
نتیجهگیری
پیادهسازی محدودیت نرخ قوی، گوشهای از امنیت برنامه است. چه به ماهیت تحملکننده ترافیک ناگهانی سطل توکن و چه به دقت پنجره لغزان روی بیاورید، درک مکانیکهای زیرین به شما اجازه میدهد دروازه API خود را به طور مؤثر پیکربندی کنید. با تعادل بین عملکرد، استفاده از حافظه و نیازهای امنیتی، میتوانید از زیرساخت خود محافظت کنید در حالی که تجربهای روان را برای کاربران خود حفظ میکنید.