یک محدود کننده نرخ طراحی کنید – انجمن DEV

Summarize this content to 400 words in Persian Lang
Rate Limiter چیست؟
در یک سیستم شبکه، یک محدود کننده نرخ، نرخ ترافیک ارسال شده توسط مشتری یا سرویس را کنترل می کند. در زمینه HTTP، یک محدودکننده نرخ، تعداد درخواستهای مشتری را که میتوان در یک دوره مشخص ارسال کرد، محدود میکند. اگر تعداد درخواستهای API از آستانه تعیینشده توسط محدودکننده نرخ بیشتر شود، تماسهای اضافی مسدود میشوند. در اینجا چند نمونه آورده شده است:
کاربر نمی تواند بیش از 2 پست در ثانیه بنویسد.
حداکثر 10 حساب در روز می تواند از همان آدرس IP ایجاد شود.
جوایز را نمی توان بیش از 5 بار در هفته از یک دستگاه دریافت کرد.
مزایای API Rate Limiter
جلوگیری از گرسنگی منابع
محدود کننده های نرخ به جلوگیری از گرسنگی منابع ناشی از حملات Denial of Service (DoS) کمک می کنند. بسیاری از شرکت های بزرگ فناوری نوعی محدودیت نرخ را اعمال می کنند. برای مثال، توییتر تعداد توییتها را به 300 توییت در 3 ساعت محدود میکند و APIهای Google Docs محدودیت پیشفرض 300 درخواست برای هر کاربر در 60 ثانیه برای درخواستهای خواندن دارند. با مسدود کردن تماسهای اضافی، یک محدودکننده نرخ میتواند از حملات DoS چه عمدی یا غیرعمدی جلوگیری کند.
کاهش هزینه های
محدود کردن درخواستهای اضافی، تعداد سرورهای مورد نیاز را کاهش میدهد و منابع بیشتری را به APIهای با اولویت بالا اختصاص میدهد. این برای شرکت هایی که از API های شخص ثالث پولی استفاده می کنند بسیار مهم است، زیرا هر تماس هزینه ای را متحمل می شود. به عنوان مثال، بررسی اعتبار، پرداخت ها، یا بازیابی سوابق سلامتی اغلب شامل هزینه های هر تماس است، که محدود کردن تعداد تماس ها برای کاهش هزینه ها ضروری است.
جلوگیری از اضافه بار سرور
برای کاهش بار سرور، یک محدود کننده نرخ درخواستهای اضافی ناشی از رباتها یا رفتار نادرست کاربر را فیلتر میکند و اطمینان میدهد که سرورها غرق نمیشوند.
درک مسئله و الزامات
ملاحظات کلیدی
نوع محدود کننده نرخ: ما بر روی یک محدود کننده نرخ API سمت سرور تمرکز خواهیم کرد.
معیارهای درگیری: محدود کننده نرخ باید به اندازه کافی انعطاف پذیر باشد تا از مجموعه های مختلف قوانین دریچه گاز مانند آدرس IP یا شناسه کاربر پشتیبانی کند.
مقیاس سیستم: سیستم باید به تعداد زیادی درخواست رسیدگی کند.
محیط توزیع شده: محدود کننده نرخ باید در یک محیط توزیع شده کار کند.
پیاده سازی: این می تواند یک سرویس جداگانه یا یکپارچه در کد برنامه باشد.
اطلاعیه های کاربر: زمانی که درخواستهای کاربران خنثی میشود باید به کاربران اطلاع داده شود.
مرحله 1: الزامات
الزامات عملکردی و غیر عملکردی
الزامات کاربردی برای طراحی Rate Limiter API:
API باید اجازه تعریف قوانین محدودکننده نرخ چندگانه را بدهد.
API باید توانایی سفارشیسازی پاسخ به مشتریان را در زمانی که از محدودیتهای نرخ فراتر میرود، ارائه دهد.
API باید امکان ذخیره سازی و بازیابی داده های محدود نرخ را فراهم کند.
API باید با مدیریت صحیح خطا پیادهسازی شود، زیرا زمانی که از حد آستانه درخواستها برای یک سرور واحد یا در ترکیبهای مختلف عبور میکند، مشتری باید یک پیام خطای مناسب دریافت کند.
الزامات غیر کاربردی برای طراحی Rate Limiter API:
API باید بسیار در دسترس و مقیاس پذیر باشد. در دسترس بودن رکن اصلی در مورد APIهای واکشی درخواست است.
API باید ایمن باشد و در برابر حملات مخرب محافظت شود.
API باید به راحتی با سیستم های موجود ادغام شود.
باید تأخیر کمی توسط محدود کننده نرخ به سیستم ارائه شود، زیرا عملکرد یکی از عوامل کلیدی در مورد هر سیستمی است.
مرحله 2: طراحی سطح بالا (HLD)
قرار دادن محدود کننده نرخ
به جای اجرای محدودکننده نرخ در سمت کلاینت یا سرور، میتوانیم یک میانافزار محدودکننده نرخ ایجاد کنیم که درخواستها به APIها را کاهش میدهد.
سناریوی نمونه
فرض کنید API ما اجازه 2 درخواست در ثانیه را می دهد. اگر یک کلاینت 3 درخواست را در یک ثانیه ارسال کند، دو درخواست اول به سرورهای API هدایت میشوند، اما درخواست سوم توسط میانافزار کنترل میشود و کد وضعیت HTTP 429 را برمیگرداند که نشاندهنده درخواستهای بسیار زیاد است.
HTTP 429 “Too Many Requests” — The user has sent too many requests in a certain amount of time. This response status code tells the user their request has been rate limited.
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
دروازه API
در معماری میکروسرویس، محدودیت نرخ اغلب در مولفه ای به نام دروازه API اجرا می شود. این یک سرویس کاملاً مدیریت شده است که از محدودیت نرخ، خاتمه SSL، احراز هویت، لیست سفید IP و سرویس محتوای ثابت پشتیبانی می کند.
ملاحظات پیاده سازی
پشته فناوری: اطمینان حاصل کنید که پشته فناوری فعلی، از جمله زبان برنامه نویسی و سرویس کش، از محدود کردن نرخ کارآمد پشتیبانی می کند.
الگوریتم محدود کردن نرخ: الگوریتمی را انتخاب کنید که متناسب با نیازهای تجاری باشد. پیاده سازی سمت سرور کنترل کامل را فراهم می کند، اما دروازه های شخص ثالث ممکن است محدودیت هایی داشته باشند.
معماری میکروسرویس: اگر از یک دروازه API برای احراز هویت و سایر خدمات استفاده می کنید، افزودن یک محدود کننده نرخ می تواند مفید باشد.
منابع مهندسی: ایجاد یک سرویس محدود کننده نرخ به زمان و منابع نیاز دارد. اگر محدود است، از یک دروازه API تجاری استفاده کنید.
معماری سطح بالا
الگوریتم های محدود کننده نرخ در سطح بالایی ساده هستند. شمارنده تعداد درخواستهای یک کاربر یا آدرس IP را ردیابی میکند. اگر شمارنده بیش از حد مجاز باشد، درخواست غیرمجاز است.
ذخیره سازی شمارنده
استفاده از پایگاه داده به دلیل کندی دسترسی به دیسک ایده آل نیست. حافظه نهان (به عنوان مثال، Redis) به دلیل سرعت و پشتیبانی از انقضای مبتنی بر زمان ترجیح داده می شود. Redis دستوراتی مانند INCR (افزایش شمارنده) و EXPIRE (تعیین زمان برای شمارنده) ارائه می دهد.
درخواست جریان
مشتری درخواستی را به میان افزار محدود کننده نرخ ارسال می کند.
میان افزار شمارنده را از Redis می گیرد و بررسی می کند که آیا به حد مجاز رسیده است یا خیر.
در صورت رسیدن به حد مجاز، درخواست رد می شود.
اگر به حد مجاز نرسیده باشد، درخواست به سرورهای API ارسال میشود، شمارنده افزایش مییابد و مقدار بهروز شده به Redis ذخیره میشود.
مرحله 3: دیپ دیو را طراحی کنید
قوانین محدود کردن نرخ
قوانین محدودکننده نرخ، شرایطی را تعریف میکنند که تحت آن درخواستها کاهش مییابد. این قوانین معمولاً در فایل های پیکربندی نوشته شده و روی دیسک ذخیره می شوند. به عنوان مثال، مجاز کردن حداکثر 5 پیام بازاریابی در روز یا محدود کردن ورود به سیستم به 5 بار در دقیقه.
رسیدگی به محدودیت های بیش از حد
وقتی درخواستی از حد مجاز فراتر رود، API کد پاسخ HTTP 429 را برمیگرداند. بسته به مورد استفاده، درخواستهای با نرخ محدود ممکن است برای پردازش بعدی در صف قرار گیرند.
سرصفحه های محدود کننده نرخ
مشتریان می توانند از طریق هدرهای پاسخ HTTP از محدودیت های نرخ مطلع شوند:
X-Ratelim-Remaining: تعداد باقیمانده درخواست های مجاز.
X-Ratelim-Limit: حداکثر تعداد درخواست های مجاز در هر پنجره زمانی.
X-Ratelim-Retry-After: تعداد ثانیه هایی که باید قبل از درخواست دیگر منتظر بمانید.
طراحی دقیق و با جزییات
قوانین بر روی دیسک ذخیره می شوند و اغلب توسط کارگران به کش کشیده می شوند.
درخواست مشتری به میان افزار محدود کننده نرخ می رود.
میان افزار قوانین را از کش بارگیری می کند و شمارنده ها را از Redis واکشی می کند.
بسته به مقدار شمارنده:
اگر درخواست محدود به نرخ نباشد، به سرورهای API ارسال می شود.
اگر درخواست محدود باشد، یک خطای HTTP 429 برگردانده میشود و ممکن است درخواست حذف شود یا در صف قرار گیرد.
چالش های محیطی توزیع شده
شرایط مسابقه
شرایط مسابقه زمانی رخ می دهد که چندین رشته به طور همزمان داده های مشترک را بخوانند و بنویسند. به عنوان مثال، دو درخواست که مقدار شمارنده را قبل از بازنویسی آن میخوانند، میتوانند منجر به شمارش نادرست شوند. راه حل ها شامل استفاده از قفل ها یا ویژگی های Redis مانند اسکریپت های Lua و مجموعه های مرتب شده است.
هماهنگ سازی
در یک محیط توزیع شده، همگام سازی تضمین می کند که سرورهای محدود کننده نرخ چندگانه داده های ثابتی دارند. جلسات چسبناک یا ذخیرههای متمرکز داده مانند Redis میتوانند به حفظ همگامسازی کمک کنند.
بهینه سازی عملکرد
راه اندازی مرکز داده چندگانه
برای کاهش تأخیر برای کاربران دور از مرکز داده، از سرورهای لبه ای استفاده کنید که به صورت جغرافیایی در سراسر جهان توزیع شده اند. ارائه دهندگان خدمات ابری مانند Cloudflare سرورهای لبه زیادی برای هدایت ترافیک به نزدیکترین آنها دارند.
سازگاری نهایی
همگام سازی داده ها با یک مدل سازگاری نهایی برای مدیریت کارآمد سیستم های مقیاس بزرگ.
الگوریتم های محدود کننده نرخ
محدود کردن نرخ را می توان با استفاده از الگوریتم های مختلف پیاده سازی کرد که هر کدام مزایا و معایب خود را دارند:
سطل توکن
تعداد ثابتی توکن در فواصل زمانی معین به یک سطل اضافه می شود. هر درخواست یک توکن مصرف می کند و اگر سطل خالی باشد، درخواست ها رد می شوند. این الگوریتم انبوه ترافیک را هموار می کند.
سطل نشتی
درخواست ها به هر میزانی به یک سطل اضافه می شوند اما با نرخ ثابتی به بیرون نشت می کنند. این الگوریتم جریان ثابت درخواست ها را تضمین می کند.
شمارنده پنجره ثابت
درخواست ها در بازه های زمانی ثابت (مثلاً در هر دقیقه) شمارش می شوند. اگر تعداد از حد مجاز بیشتر شود، درخواست ها رد می شود.
گزارش پنجره کشویی
مهرهای زمانی درخواست را در یک گزارش ردیابی میکند و درخواستها را در یک پنجره زمانی کشویی شمارش میکند، که در مقایسه با پنجرههای ثابت محدودیتهای نرمتری ارائه میدهد.
شمارنده پنجره کشویی
ترکیبی از شمارنده پنجره ثابت و سیاهه پنجره کشویی، تعادلی بین سادگی و دقت ایجاد می کند.
محدود کننده نرخ با استفاده از مجموعه مرتب شده در Redis
قطعا! پیاده سازی یک محدود کننده نرخ با استفاده از یک مجموعه مرتب شده در Redis یک روش قوی است، به خصوص در یک شبکه توزیع شده. در اینجا توضیح عمیقی در مورد نحوه عملکرد آن به همراه یک مثال آورده شده است:
چگونه مجموعه های مرتب شده در Redis برای محدود کردن نرخ کار می کنند
مجموعه مرتب شده در Redis مجموعه ای از عناصر منحصر به فرد است که هر کدام با یک امتیاز مرتبط هستند. عناصر بر اساس امتیازهایشان مرتب می شوند که می تواند هر مقدار ممیز شناور باشد. این مرتبسازی به درخواستهای محدوده کارآمد اجازه میدهد، که برای پیادهسازی یک محدودکننده نرخ بسیار مهم است.
مفاهیم کلیدی
عناصر: درخواست های مشتری را نمایندگی کنید.
امتیازات: نشان دهنده مُهر زمانی درخواست ها است.
مراحل اجرای محدودیت نرخ با استفاده از مجموعه های مرتب شده
مجموعه مرتب شده را راه اندازی کنید: برای هر کلاینت (که با یک کلید منحصر به فرد مانند آدرس IP یا شناسه کاربر مشخص می شود)، یک مجموعه مرتب شده در Redis نگه دارید که در آن عناصر شناسه درخواست هستند (ممکن است یک شناسه درخواست منحصر به فرد یا فقط یک تعداد باشد) و امتیازها مُهر زمانی هستند. درخواست ها.
افزودن یک درخواست: هنگامی که یک مشتری درخواستی را ارائه می دهد، یک ورودی به مجموعه مرتب شده با مهر زمانی فعلی به عنوان امتیاز اضافه کنید.
کوتاه کردن درخواست های قدیمی: به صورت دوره ای یا در هر درخواست، ورودی هایی را از مجموعه مرتب شده حذف کنید که خارج از پنجره زمانی مجاز قرار می گیرند.
شمارش درخواست ها: تعداد عناصر موجود در مجموعه مرتب شده را بشمارید تا بررسی کنید که آیا از حد مجاز فراتر رفته است یا خیر.
اجرای محدودیت ها: اگر تعداد از حد مجاز بیشتر شد، درخواست را رد کنید. اگر نه، درخواست را پردازش کنید و ورودی جدید را به مجموعه اضافه کنید.
مثال
فرض کنید می خواهیم یک کاربر را به 100 درخواست در ساعت محدود کنیم.
پیاده سازی گام به گام
مقداردهی اولیه: در Redis نیازی به مقداردهی اولیه نیست. Redis در اولین استفاده مجموعه مرتب شده را ایجاد می کند.
رسیدگی به درخواست:
یک درخواست اضافه کنید: وقتی درخواستی ارسال شد، مهر زمانی فعلی را دریافت کنید.
import time
current_timestamp = int(time.time())
به مجموعه مرتب شده اضافه کنید:
client_id = “user123” # Example client ID
request_id = “req456” # Example request ID (could be unique or a counter)
redis.zadd(client_id, {request_id: current_timestamp})
درخواست های قدیمی را اصلاح کنید: درخواست های قدیمی تر از 1 ساعت (3600 ثانیه) را حذف کنید.
one_hour_ago = current_timestamp – 3600
redis.zremrangebyscore(client_id, 0, one_hour_ago)
تعداد درخواست ها: تعداد درخواست های یک ساعت گذشته را دریافت کنید.
request_count = redis.zcount(client_id, one_hour_ago, current_timestamp)
محدودیت را اجرا کنید: بررسی کنید که آیا تعداد درخواست ها از حد مجاز فراتر رفته است.
if request_count >= 100:
print(“Rate limit exceeded”)
# Deny the request
else:
print(“Request allowed”)
# Process the request
مدیریت همزمانی
در یک محیط توزیع شده، چندین سرور ممکن است درخواستهای یک کلاینت را به طور همزمان مدیریت کنند. Redis اتمی بودن دستورات را کنترل میکند و تضمین میکند که حتی با دسترسی همزمان، عملیات (مانند افزودن یک درخواست یا برش درخواستهای قدیمی) با خیال راحت انجام میشود.
کد نمونه تفصیلی
در اینجا یک مثال کد دقیق تر با استفاده از Redis با Python و the است redis-py کتابخانه:
import redis
import time
# Connect to Redis
r = redis.StrictRedis(host=’localhost’, port=6379, db=0)
# Function to handle a request
def handle_request(client_id, request_id, limit, window):
current_timestamp = int(time.time())
one_hour_ago = current_timestamp – window
# Transaction to ensure atomic operations
with r.pipeline() as pipe:
# Add the current request
pipe.zadd(client_id, {request_id: current_timestamp})
# Remove old requests
pipe.zremrangebyscore(client_id, 0, one_hour_ago)
# Count the number of requests in the time window
pipe.zcount(client_id, one_hour_ago, current_timestamp)
# Execute the pipeline
_, _, request_count = pipe.execute()
# Check if the request count exceeds the limit
if request_count >= limit:
return False # Rate limit exceeded
else:
return True # Request allowed
# Example usage
client_id = “user123”
request_id = “req456”
limit = 100 # Maximum 100 requests
window = 3600 # Time window of 1 hour
if handle_request(client_id, request_id, limit, window):
print(“Request allowed”)
else:
print(“Rate limit exceeded”)
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مزایای استفاده از مجموعه های مرتب شده در Redis
بهره وری: مجموعه های مرتب شده در Redis برای درج سریع، حذف و جستجوهای محدوده بهینه شده اند که برای محدود کردن نرخ ضروری هستند.
عملیات اتمی: Redis از عملیات اتمی پشتیبانی می کند و اطمینان می دهد که تغییرات همزمان با خیال راحت انجام می شوند.
مقیاس پذیری: Redis برای مدیریت سناریوهای با توان بالا طراحی شده است و آن را برای محیط های توزیع شده مناسب می کند.
با استفاده از مجموعههای مرتبشده و عملیات اتمی Redis، میتوانید یک محدودکننده نرخ قوی و مقیاسپذیر بسازید که به طور موثر نرخ درخواستهای مشتری را در یک شبکه توزیعشده کنترل میکند.
نتیجه
طراحی یک محدود کننده نرخ موثر شامل درک الزامات، انتخاب الگوریتم های مناسب و در نظر گرفتن چالش های عملکرد و هماهنگ سازی در یک محیط توزیع شده است. استفاده از ابزارهایی مانند Redis می تواند پیاده سازی را ساده کرده و عملکرد بالا را تضمین کند.
Rate Limiter چیست؟
در یک سیستم شبکه، یک محدود کننده نرخ، نرخ ترافیک ارسال شده توسط مشتری یا سرویس را کنترل می کند. در زمینه HTTP، یک محدودکننده نرخ، تعداد درخواستهای مشتری را که میتوان در یک دوره مشخص ارسال کرد، محدود میکند. اگر تعداد درخواستهای API از آستانه تعیینشده توسط محدودکننده نرخ بیشتر شود، تماسهای اضافی مسدود میشوند. در اینجا چند نمونه آورده شده است:
- کاربر نمی تواند بیش از 2 پست در ثانیه بنویسد.
- حداکثر 10 حساب در روز می تواند از همان آدرس IP ایجاد شود.
- جوایز را نمی توان بیش از 5 بار در هفته از یک دستگاه دریافت کرد.
مزایای API Rate Limiter
جلوگیری از گرسنگی منابع
محدود کننده های نرخ به جلوگیری از گرسنگی منابع ناشی از حملات Denial of Service (DoS) کمک می کنند. بسیاری از شرکت های بزرگ فناوری نوعی محدودیت نرخ را اعمال می کنند. برای مثال، توییتر تعداد توییتها را به 300 توییت در 3 ساعت محدود میکند و APIهای Google Docs محدودیت پیشفرض 300 درخواست برای هر کاربر در 60 ثانیه برای درخواستهای خواندن دارند. با مسدود کردن تماسهای اضافی، یک محدودکننده نرخ میتواند از حملات DoS چه عمدی یا غیرعمدی جلوگیری کند.
کاهش هزینه های
محدود کردن درخواستهای اضافی، تعداد سرورهای مورد نیاز را کاهش میدهد و منابع بیشتری را به APIهای با اولویت بالا اختصاص میدهد. این برای شرکت هایی که از API های شخص ثالث پولی استفاده می کنند بسیار مهم است، زیرا هر تماس هزینه ای را متحمل می شود. به عنوان مثال، بررسی اعتبار، پرداخت ها، یا بازیابی سوابق سلامتی اغلب شامل هزینه های هر تماس است، که محدود کردن تعداد تماس ها برای کاهش هزینه ها ضروری است.
جلوگیری از اضافه بار سرور
برای کاهش بار سرور، یک محدود کننده نرخ درخواستهای اضافی ناشی از رباتها یا رفتار نادرست کاربر را فیلتر میکند و اطمینان میدهد که سرورها غرق نمیشوند.
درک مسئله و الزامات
ملاحظات کلیدی
- نوع محدود کننده نرخ: ما بر روی یک محدود کننده نرخ API سمت سرور تمرکز خواهیم کرد.
- معیارهای درگیری: محدود کننده نرخ باید به اندازه کافی انعطاف پذیر باشد تا از مجموعه های مختلف قوانین دریچه گاز مانند آدرس IP یا شناسه کاربر پشتیبانی کند.
- مقیاس سیستم: سیستم باید به تعداد زیادی درخواست رسیدگی کند.
- محیط توزیع شده: محدود کننده نرخ باید در یک محیط توزیع شده کار کند.
- پیاده سازی: این می تواند یک سرویس جداگانه یا یکپارچه در کد برنامه باشد.
- اطلاعیه های کاربر: زمانی که درخواستهای کاربران خنثی میشود باید به کاربران اطلاع داده شود.
مرحله 1: الزامات
الزامات عملکردی و غیر عملکردی
الزامات کاربردی برای طراحی Rate Limiter API:
- API باید اجازه تعریف قوانین محدودکننده نرخ چندگانه را بدهد.
- API باید توانایی سفارشیسازی پاسخ به مشتریان را در زمانی که از محدودیتهای نرخ فراتر میرود، ارائه دهد.
- API باید امکان ذخیره سازی و بازیابی داده های محدود نرخ را فراهم کند.
- API باید با مدیریت صحیح خطا پیادهسازی شود، زیرا زمانی که از حد آستانه درخواستها برای یک سرور واحد یا در ترکیبهای مختلف عبور میکند، مشتری باید یک پیام خطای مناسب دریافت کند.
الزامات غیر کاربردی برای طراحی Rate Limiter API:
- API باید بسیار در دسترس و مقیاس پذیر باشد. در دسترس بودن رکن اصلی در مورد APIهای واکشی درخواست است.
- API باید ایمن باشد و در برابر حملات مخرب محافظت شود.
- API باید به راحتی با سیستم های موجود ادغام شود.
- باید تأخیر کمی توسط محدود کننده نرخ به سیستم ارائه شود، زیرا عملکرد یکی از عوامل کلیدی در مورد هر سیستمی است.
مرحله 2: طراحی سطح بالا (HLD)
قرار دادن محدود کننده نرخ
به جای اجرای محدودکننده نرخ در سمت کلاینت یا سرور، میتوانیم یک میانافزار محدودکننده نرخ ایجاد کنیم که درخواستها به APIها را کاهش میدهد.
سناریوی نمونه
فرض کنید API ما اجازه 2 درخواست در ثانیه را می دهد. اگر یک کلاینت 3 درخواست را در یک ثانیه ارسال کند، دو درخواست اول به سرورهای API هدایت میشوند، اما درخواست سوم توسط میانافزار کنترل میشود و کد وضعیت HTTP 429 را برمیگرداند که نشاندهنده درخواستهای بسیار زیاد است.
HTTP 429 "Too Many Requests" — The user has sent too many requests in a certain amount of time. This response status code tells the user their request has been rate limited.
دروازه API
در معماری میکروسرویس، محدودیت نرخ اغلب در مولفه ای به نام دروازه API اجرا می شود. این یک سرویس کاملاً مدیریت شده است که از محدودیت نرخ، خاتمه SSL، احراز هویت، لیست سفید IP و سرویس محتوای ثابت پشتیبانی می کند.
ملاحظات پیاده سازی
- پشته فناوری: اطمینان حاصل کنید که پشته فناوری فعلی، از جمله زبان برنامه نویسی و سرویس کش، از محدود کردن نرخ کارآمد پشتیبانی می کند.
- الگوریتم محدود کردن نرخ: الگوریتمی را انتخاب کنید که متناسب با نیازهای تجاری باشد. پیاده سازی سمت سرور کنترل کامل را فراهم می کند، اما دروازه های شخص ثالث ممکن است محدودیت هایی داشته باشند.
- معماری میکروسرویس: اگر از یک دروازه API برای احراز هویت و سایر خدمات استفاده می کنید، افزودن یک محدود کننده نرخ می تواند مفید باشد.
- منابع مهندسی: ایجاد یک سرویس محدود کننده نرخ به زمان و منابع نیاز دارد. اگر محدود است، از یک دروازه API تجاری استفاده کنید.
معماری سطح بالا
الگوریتم های محدود کننده نرخ در سطح بالایی ساده هستند. شمارنده تعداد درخواستهای یک کاربر یا آدرس IP را ردیابی میکند. اگر شمارنده بیش از حد مجاز باشد، درخواست غیرمجاز است.
ذخیره سازی شمارنده
استفاده از پایگاه داده به دلیل کندی دسترسی به دیسک ایده آل نیست. حافظه نهان (به عنوان مثال، Redis) به دلیل سرعت و پشتیبانی از انقضای مبتنی بر زمان ترجیح داده می شود. Redis دستوراتی مانند INCR (افزایش شمارنده) و EXPIRE (تعیین زمان برای شمارنده) ارائه می دهد.
درخواست جریان
- مشتری درخواستی را به میان افزار محدود کننده نرخ ارسال می کند.
- میان افزار شمارنده را از Redis می گیرد و بررسی می کند که آیا به حد مجاز رسیده است یا خیر.
- در صورت رسیدن به حد مجاز، درخواست رد می شود.
- اگر به حد مجاز نرسیده باشد، درخواست به سرورهای API ارسال میشود، شمارنده افزایش مییابد و مقدار بهروز شده به Redis ذخیره میشود.
مرحله 3: دیپ دیو را طراحی کنید
قوانین محدود کردن نرخ
قوانین محدودکننده نرخ، شرایطی را تعریف میکنند که تحت آن درخواستها کاهش مییابد. این قوانین معمولاً در فایل های پیکربندی نوشته شده و روی دیسک ذخیره می شوند. به عنوان مثال، مجاز کردن حداکثر 5 پیام بازاریابی در روز یا محدود کردن ورود به سیستم به 5 بار در دقیقه.
رسیدگی به محدودیت های بیش از حد
وقتی درخواستی از حد مجاز فراتر رود، API کد پاسخ HTTP 429 را برمیگرداند. بسته به مورد استفاده، درخواستهای با نرخ محدود ممکن است برای پردازش بعدی در صف قرار گیرند.
سرصفحه های محدود کننده نرخ
مشتریان می توانند از طریق هدرهای پاسخ HTTP از محدودیت های نرخ مطلع شوند:
- X-Ratelim-Remaining: تعداد باقیمانده درخواست های مجاز.
- X-Ratelim-Limit: حداکثر تعداد درخواست های مجاز در هر پنجره زمانی.
- X-Ratelim-Retry-After: تعداد ثانیه هایی که باید قبل از درخواست دیگر منتظر بمانید.
طراحی دقیق و با جزییات
- قوانین بر روی دیسک ذخیره می شوند و اغلب توسط کارگران به کش کشیده می شوند.
- درخواست مشتری به میان افزار محدود کننده نرخ می رود.
- میان افزار قوانین را از کش بارگیری می کند و شمارنده ها را از Redis واکشی می کند.
- بسته به مقدار شمارنده:
- اگر درخواست محدود به نرخ نباشد، به سرورهای API ارسال می شود.
- اگر درخواست محدود باشد، یک خطای HTTP 429 برگردانده میشود و ممکن است درخواست حذف شود یا در صف قرار گیرد.
چالش های محیطی توزیع شده
شرایط مسابقه
شرایط مسابقه زمانی رخ می دهد که چندین رشته به طور همزمان داده های مشترک را بخوانند و بنویسند. به عنوان مثال، دو درخواست که مقدار شمارنده را قبل از بازنویسی آن میخوانند، میتوانند منجر به شمارش نادرست شوند. راه حل ها شامل استفاده از قفل ها یا ویژگی های Redis مانند اسکریپت های Lua و مجموعه های مرتب شده است.
هماهنگ سازی
در یک محیط توزیع شده، همگام سازی تضمین می کند که سرورهای محدود کننده نرخ چندگانه داده های ثابتی دارند. جلسات چسبناک یا ذخیرههای متمرکز داده مانند Redis میتوانند به حفظ همگامسازی کمک کنند.
بهینه سازی عملکرد
راه اندازی مرکز داده چندگانه
برای کاهش تأخیر برای کاربران دور از مرکز داده، از سرورهای لبه ای استفاده کنید که به صورت جغرافیایی در سراسر جهان توزیع شده اند. ارائه دهندگان خدمات ابری مانند Cloudflare سرورهای لبه زیادی برای هدایت ترافیک به نزدیکترین آنها دارند.
سازگاری نهایی
همگام سازی داده ها با یک مدل سازگاری نهایی برای مدیریت کارآمد سیستم های مقیاس بزرگ.
الگوریتم های محدود کننده نرخ
محدود کردن نرخ را می توان با استفاده از الگوریتم های مختلف پیاده سازی کرد که هر کدام مزایا و معایب خود را دارند:
سطل توکن
تعداد ثابتی توکن در فواصل زمانی معین به یک سطل اضافه می شود. هر درخواست یک توکن مصرف می کند و اگر سطل خالی باشد، درخواست ها رد می شوند. این الگوریتم انبوه ترافیک را هموار می کند.
سطل نشتی
درخواست ها به هر میزانی به یک سطل اضافه می شوند اما با نرخ ثابتی به بیرون نشت می کنند. این الگوریتم جریان ثابت درخواست ها را تضمین می کند.
شمارنده پنجره ثابت
درخواست ها در بازه های زمانی ثابت (مثلاً در هر دقیقه) شمارش می شوند. اگر تعداد از حد مجاز بیشتر شود، درخواست ها رد می شود.
گزارش پنجره کشویی
مهرهای زمانی درخواست را در یک گزارش ردیابی میکند و درخواستها را در یک پنجره زمانی کشویی شمارش میکند، که در مقایسه با پنجرههای ثابت محدودیتهای نرمتری ارائه میدهد.
شمارنده پنجره کشویی
ترکیبی از شمارنده پنجره ثابت و سیاهه پنجره کشویی، تعادلی بین سادگی و دقت ایجاد می کند.
محدود کننده نرخ با استفاده از مجموعه مرتب شده در Redis
قطعا! پیاده سازی یک محدود کننده نرخ با استفاده از یک مجموعه مرتب شده در Redis یک روش قوی است، به خصوص در یک شبکه توزیع شده. در اینجا توضیح عمیقی در مورد نحوه عملکرد آن به همراه یک مثال آورده شده است:
چگونه مجموعه های مرتب شده در Redis برای محدود کردن نرخ کار می کنند
مجموعه مرتب شده در Redis مجموعه ای از عناصر منحصر به فرد است که هر کدام با یک امتیاز مرتبط هستند. عناصر بر اساس امتیازهایشان مرتب می شوند که می تواند هر مقدار ممیز شناور باشد. این مرتبسازی به درخواستهای محدوده کارآمد اجازه میدهد، که برای پیادهسازی یک محدودکننده نرخ بسیار مهم است.
مفاهیم کلیدی
- عناصر: درخواست های مشتری را نمایندگی کنید.
- امتیازات: نشان دهنده مُهر زمانی درخواست ها است.
مراحل اجرای محدودیت نرخ با استفاده از مجموعه های مرتب شده
-
مجموعه مرتب شده را راه اندازی کنید: برای هر کلاینت (که با یک کلید منحصر به فرد مانند آدرس IP یا شناسه کاربر مشخص می شود)، یک مجموعه مرتب شده در Redis نگه دارید که در آن عناصر شناسه درخواست هستند (ممکن است یک شناسه درخواست منحصر به فرد یا فقط یک تعداد باشد) و امتیازها مُهر زمانی هستند. درخواست ها.
-
افزودن یک درخواست: هنگامی که یک مشتری درخواستی را ارائه می دهد، یک ورودی به مجموعه مرتب شده با مهر زمانی فعلی به عنوان امتیاز اضافه کنید.
-
کوتاه کردن درخواست های قدیمی: به صورت دوره ای یا در هر درخواست، ورودی هایی را از مجموعه مرتب شده حذف کنید که خارج از پنجره زمانی مجاز قرار می گیرند.
-
شمارش درخواست ها: تعداد عناصر موجود در مجموعه مرتب شده را بشمارید تا بررسی کنید که آیا از حد مجاز فراتر رفته است یا خیر.
-
اجرای محدودیت ها: اگر تعداد از حد مجاز بیشتر شد، درخواست را رد کنید. اگر نه، درخواست را پردازش کنید و ورودی جدید را به مجموعه اضافه کنید.
مثال
فرض کنید می خواهیم یک کاربر را به 100 درخواست در ساعت محدود کنیم.
پیاده سازی گام به گام
-
مقداردهی اولیه: در Redis نیازی به مقداردهی اولیه نیست. Redis در اولین استفاده مجموعه مرتب شده را ایجاد می کند.
-
رسیدگی به درخواست:
-
یک درخواست اضافه کنید: وقتی درخواستی ارسال شد، مهر زمانی فعلی را دریافت کنید.
import time current_timestamp = int(time.time())
-
به مجموعه مرتب شده اضافه کنید:
client_id = "user123" # Example client ID request_id = "req456" # Example request ID (could be unique or a counter) redis.zadd(client_id, {request_id: current_timestamp})
-
درخواست های قدیمی را اصلاح کنید: درخواست های قدیمی تر از 1 ساعت (3600 ثانیه) را حذف کنید.
one_hour_ago = current_timestamp - 3600 redis.zremrangebyscore(client_id, 0, one_hour_ago)
-
تعداد درخواست ها: تعداد درخواست های یک ساعت گذشته را دریافت کنید.
request_count = redis.zcount(client_id, one_hour_ago, current_timestamp)
-
محدودیت را اجرا کنید: بررسی کنید که آیا تعداد درخواست ها از حد مجاز فراتر رفته است.
if request_count >= 100: print("Rate limit exceeded") # Deny the request else: print("Request allowed") # Process the request
مدیریت همزمانی
در یک محیط توزیع شده، چندین سرور ممکن است درخواستهای یک کلاینت را به طور همزمان مدیریت کنند. Redis اتمی بودن دستورات را کنترل میکند و تضمین میکند که حتی با دسترسی همزمان، عملیات (مانند افزودن یک درخواست یا برش درخواستهای قدیمی) با خیال راحت انجام میشود.
کد نمونه تفصیلی
در اینجا یک مثال کد دقیق تر با استفاده از Redis با Python و the است redis-py
کتابخانه:
import redis
import time
# Connect to Redis
r = redis.StrictRedis(host='localhost', port=6379, db=0)
# Function to handle a request
def handle_request(client_id, request_id, limit, window):
current_timestamp = int(time.time())
one_hour_ago = current_timestamp - window
# Transaction to ensure atomic operations
with r.pipeline() as pipe:
# Add the current request
pipe.zadd(client_id, {request_id: current_timestamp})
# Remove old requests
pipe.zremrangebyscore(client_id, 0, one_hour_ago)
# Count the number of requests in the time window
pipe.zcount(client_id, one_hour_ago, current_timestamp)
# Execute the pipeline
_, _, request_count = pipe.execute()
# Check if the request count exceeds the limit
if request_count >= limit:
return False # Rate limit exceeded
else:
return True # Request allowed
# Example usage
client_id = "user123"
request_id = "req456"
limit = 100 # Maximum 100 requests
window = 3600 # Time window of 1 hour
if handle_request(client_id, request_id, limit, window):
print("Request allowed")
else:
print("Rate limit exceeded")
مزایای استفاده از مجموعه های مرتب شده در Redis
- بهره وری: مجموعه های مرتب شده در Redis برای درج سریع، حذف و جستجوهای محدوده بهینه شده اند که برای محدود کردن نرخ ضروری هستند.
- عملیات اتمی: Redis از عملیات اتمی پشتیبانی می کند و اطمینان می دهد که تغییرات همزمان با خیال راحت انجام می شوند.
- مقیاس پذیری: Redis برای مدیریت سناریوهای با توان بالا طراحی شده است و آن را برای محیط های توزیع شده مناسب می کند.
با استفاده از مجموعههای مرتبشده و عملیات اتمی Redis، میتوانید یک محدودکننده نرخ قوی و مقیاسپذیر بسازید که به طور موثر نرخ درخواستهای مشتری را در یک شبکه توزیعشده کنترل میکند.
نتیجه
طراحی یک محدود کننده نرخ موثر شامل درک الزامات، انتخاب الگوریتم های مناسب و در نظر گرفتن چالش های عملکرد و هماهنگ سازی در یک محیط توزیع شده است. استفاده از ابزارهایی مانند Redis می تواند پیاده سازی را ساده کرده و عملکرد بالا را تضمین کند.