Deep Dive Into Rate Limiting

الـ Rate Limiting هو واحد من أهم الـ Mechanisms اللي بنستخدمها في الـ Software Systems اللي عاوزينها تكون Scalable و Secure عشان نتحكم في كمية الـ Requests اللي ممكن النظام يعالجها في وقت معين.
Deep Dive Into Rate Limiting
Deep Dive Into Rate Limiting

في هذه الصفحة

المقدمة

الـ Rate Limiting هو واحد من أهم الـ Mechanisms اللي بنستخدمها في الـ Software Systems اللي عاوزينها تكون Scalable و Secure عشان نتحكم في كمية الـ Requests اللي ممكن النظام يعالجها في وقت معين.

الفكرة الأساسية هي إننا نحمي النظام من الـ abuse، سواء من users بيحاولوا يستهلكوا موارد زيادة أو من هجمات زي الـ DDoS.

فخلونا نتعرف أكتر عنه لإنه أحد الأجزاء الرئيسية في وقتنا الحالي خصوصا في الـ Distributed Systems وبنحتاجه احياناً واحنا بنعمل System Design ، وهنشرح برضو أنواع الـ algorithms المختلفة المستخدمة في الـ Rate Limiting وازاي تختار الأنسب لنظامك.

واتكلمنا في ورقة وقلم عن الموضوع ده قبل كده :

Rate Limiting In a Nutshell
ال Rate Limiting هي واحدة من أهم الطرق الأساسية عشان نحقق الـ Robustness في الـ Service اللي بنبنيها وده من خلال تحديد عدد Requests معينة مسموح للمستخدم يطلبها في فترة زمنية محددة.

Rate Limiting In a Nutshell


ليه ممكن نحتاج الـ Rate Limiting

الـ Rate Limiting مش مجرد فكرة لحماية النظام من الـ abuse، ولكنه بيقدم layers من الـ control والـ scalability اللي بتحمي الـ backend من مشاكل مختلفة زي:

  1. الـ Overload على الـ Resources:
    عدد كبير جدًا من الـ requests ممكن يسبب ضغط على الـ servers، وده بيأثر على الـ performance لكل المستخدمين.
  2. حماية الـ APIs من الـ abuse:
    سواء كان هجوم DDoS أو user بيحاول يعمل spam.
  3. تحسين تجربة المستخدم:
    لما نضمن إن كل المستخدمين بياخدوا نصيب عادل من الـ resources، ده بيحسن الـ UX ككل بالنسبة للمستخدمين.

المكونات الرئيسية لأي Rate Limiter

علشان نفهم الـ Rate Limiting بعمق، لازم نبص على المكونات الأساسية اللي بتكوّن أي implementation ألا وهي:

المكونات الرئيسية للـ Rate Limiting
  1. الـ Quota:
    وده بيكون الحد الأقصى للـ requests اللي ممكن client يعمله خلال فترة زمنية معينة (مثلاً 100 request لكل دقيقة) وطبعًا لو حاولتوا تعملوا Integration مع Third Party APIs بتلاقوا الـ Quota دي محددة ولو بتعديها بيبدأ الـ System يبعتلك Errors على الـ Requests اللي بتبعتها.
  2. الـ Interval:
    الفترة الزمنية اللي بيتم فيها تطبيق الـ limit (مثلاً دقيقة، أو ساعة).
  3. الـ Policy:
    القواعد اللي بتحدد الـ behavior لما الـ limit يتعدى ودي بتختلف باختلاف نوع الـ System زي:
    • إننا نـ Reject requests فورًا ونبعت للـ clients انهم تعدوا الـ Quota.
    • ممكن نعمل Delay requests بحيث يستنوا فترة أطول وبعدين يتنفذوا.
    • وممكن نـ Apply exponential backoff ودي باننا بنستنى بوقت Exponential مش Fixed وليكن أول مرة هنستنى ثانيتين بعدين 4 وبعدين 8 وبعدين 16.
  4. الـ Storage:
    ودي مهمة عشان نقدر نتتبع الـ requests، فالـ Rate Limiting implementation محتاج يخزن معلومات زي timestamps وعدد الـ requests. وكل ده ضروري عشان نعرف نـ Apply الـ Rate Limiting فممكن يتنفذ باستخدام:
    • الـ In-Memory Storage: ممكن نطبق الـ Rate Limiting باستعمال Redis أو Memcached.
    • الـ Distributed Systems: لو الـ API بتشتغل على أكتر من server وعاوزين نـ Apply Rate Limiting على الـ API ده فمش هينفع كل Machine تخزن Local المعلومات دي فمحتاجين Distributed Systems نقدر نرجع ليه بالنسبة لكل الـ Servers اللي موجودة.

التحديات اللي بتواجهنا في تطبيق الـ Rate Limiting

تطبيق الـ Rate Limiting بيجي مع مجموعة من التحديات اللي محتاجة حلول مبتكرة زي:

  1. الـ Sync بين الـ Distributed Systems:
    لو عندنا أكتر من instance للنظام، لازم نتأكد إن كل الـ instances متزامنة في تتبع الـ requests، وده ممكن يتم باستخدام distributed storage زي Redis.
  2. الـ Rate Limiting لـ Clients مختلفين:
    أحيانًا بنحتاج نعمل Rate Limiting مختلف لكل نوع من الـ clients (مثلاً user عادي vs. premium user).
  3. الـ Handling للـ Bursty Traffic:
    الـ traffic مش دايمًا بيكون steady، وبالتالي لازم نختار algorithm مرن في التعامل مع النوع ده من الـ Traffic والـ Bursty traffic هو نوع من الـ traffic اللي بيحصل بشكل غير منتظم، بيظهر فيه فترات قصيرة فيها كمية requests كبيرة جدًا (burst)، وبعدها ممكن تكون فيه فترات هدوء أو requests قليلة جدًا.
  4. تجنب الـ Overhead:
    تطبيق الـ Rate Limiting مش المفروض يكون عبء على النظام نفسه. وبالتالي محتاجين اختيارنا للـ efficient algorithms والـ storage solutions يكون بيقلل من الـ overhead ده.

Rate Limiting Algorithms

عشان نطبق الـ Rate Limiting في الـ Systems بتاعتنا محتاجين نفهم أن فيه أكتر من Algorithms نقدر من خلالهم نطبق المفهوم ده ، وكل Algorithm بيختلف عن التاني في بعض النقاط زي السهولة والتعقيد أو الدقة أو ضرورة الاستعمال اللي تخلينا نختاره عن Algorithm تاني.

خلونا نشوف بعض وأشهر الـ Algorithms المستخدمة في تطبيق الـ Rate Limiting:

  • Fixed Window Counter
  • Sliding Window Log
  • Sliding Window Counter
  • Token Bucket
  • Leaky Bucket

Fixed Window Counter

إزاي الـ Fixed Window بيشتغل:

الـ Fixed Window هو أبسط algorithm لتطبيق الـ Rate Limiting. وفكرته ببساطة هي إنه بيقسم الوقت لـ windows ثابتة (مثلاً كل دقيقة) وبيسمح بعدد معين من الـ requests لكل window.

لو العدد تعدى الحد المسموح، الـ requests الزايدة بتترفض أو على حسب الـ Policy زي ما شوفنا في المكونات الرئيسية للـ Rate Limiter.

مميزات الـ Fixed Window:

  • بسيط وسهل التنفيذ.
  • مناسب للـ use cases اللي مش بتحتاج دقة عالية في تطبيق الـ Rate Limiting.

عيوب الـ Fixed Window:

مش دقيق، خصوصًا لو الـ requests وصلت في نهاية window وبداية window جديدة فموضوع الـ Overlapping ده والدقة مش بيكون أفضل حاجة فيه.

إمتى نستخدم الـ Fixed Window:

لو كانت الـ APIs اللي شغالين عليها مش بتحتاج rate control دقيق جدًا.

Fixed Window - Rate Limiting Algorithm

Fixed Window Rate Limiter in Python

تعالوا نشوف تطبيق ده في الكود ممكن يكون شكله عامل ازاي ، والـ Code Snippet ده باستعمال ChatGPT:

import time

class FixedWindowRateLimiter:
    def __init__(self, limit, window_size):
        self.limit = limit
        self.window_size = window_size
        self.window_start = time.time()
        self.request_count = 0

    def allow_request(self):
        current_time = time.time()
        if current_time - self.window_start > self.window_size:
            # Reset the window
            self.window_start = current_time
            self.request_count = 0

        if self.request_count < self.limit:
            self.request_count += 1
            return True
        else:
            return False

# Example Usage
limiter = FixedWindowRateLimiter(limit=5, window_size=10)  # 5 requests every 10 seconds

for i in range(10):
    if limiter.allow_request():
        print(f"Request {i + 1} allowed.")
    else:
        print(f"Request {i + 1} denied.")
    time.sleep(1)

تقدروا دلوقتي تشتركوا في النشرة الأسبوعية لاقرأ-تِك بشكل مجاني تمامًا عشان يجيلكوا كل جديد بشكل أسبوعي فيما يخص مواضيع متنوعة وبشروحات بسيطة وسهلة وبجودة عالية 🚀

النشرة هيكون ليها شكل جديد ومختلف عن شكلها القديم وهنحاول انها تكون مميزة ومختلفة وخليط بين المحتوى الأساسي اللي بينزل ومفاجآت تانية كتير 🎉

Eqraatech Newsletter | Eqraatech - اقرأ-تِك | Substack
محتوى تقني متميز في مختلف مجالات هندسة البرمجيات باللغة العربية عن طريق تبسيط المفاهيم البرمجية المعقدة بشكل سلس وباستخدام صور توضيحية مذهلة. Click to read Eqraatech Newsletter, a Substack publication with hundreds of subscribers.

بفضل الله قمنا بإطلاق قناة اقرأ-تِك على التليجرام مجانًا للجميع 🚀

آملين بده اننا نفتح باب تاني لتحقيق رؤيتنا نحو إثراء المحتوى التقني باللغة العربية ، ومساعدة لكل متابعينا في انهم يوصلوا لجميع أخبار اقرأ-تِك من حيث المقالات ومحتوى ورقة وقلم والنشرة الأسبوعية وكل جديد بطريقة سريعة وسهلة

مستنينكوا تنورونا , وده رابط القناة 👇

https://t.me/eqraatechcom


Sliding Window Log

إزاي الـ Sliding Window Log بيشتغل:

الـ Sliding Window بيستخدم الـ timestamps اللي جاية مع الـ Request عشان يقدر يتتبع الـ requests ويحسب المعدل بشكل متحرك. وده بيخليه أكتر دقة من الـ Fixed Window.

  • بيتتبع timestamps لكل request باستخدام الـ Data Structure زي deque أو list.
  • بيحذف الـ timestamps القديمة اللي مش في الـ window الزمنية الحالية.
  • بيحسب عدد الـ requests في الـ window علشان يقرر إذا كان هيقبل request جديد أو يرفضه.

مميزات الـ Sliding Window Log:

  • أدق في تتبع الـ requests خصوصًا في حل مشكلة الـ Overlapping والـ Edges اللي شوفناها بتواجه الـ Fixed Window.
  • بيوفر توزيع عادل أكتر للـ requests لإنه متحرك مش ثابت فكل Request Timestamp جه بيبدأ من اللحظة دي لحد الـ Window ما تنتهي.

عيوب الـ Sliding Window Log:

  • أكتر تعقيد في التنفيذ.
  • ممكن يستهلك موارد كتير جدًا في حالة ان كان فيه High Volume Requests وده لإنه بيخزن الـ Request Timestamps عشان يعرف يحرك الـ Window ويكون دقيق.

إمتى نستخدم الـ Sliding Window Log:

لو كانت الـ APIs اللي شغالين عليهابتحتاج rate control دقيق جدًا وفي نفس الوقت مش High Volume.

Sliding Window Log - Rate Limiting Algorithm

Sliding Window Log Rate Limiter in Python

تعالوا نشوف تطبيق ده في الكود ممكن يكون شكله عامل ازاي ، والـ Code Snippet ده باستعمال ChatGPT:

from collections import deque
import time

class SlidingWindowRateLimiter:
    def __init__(self, limit, window_size):
        self.limit = limit
        self.window_size = window_size
        self.request_timestamps = deque()

    def allow_request(self):
        current_time = time.time()

        # Remove old requests
        while self.request_timestamps and self.request_timestamps[0] < current_time - self.window_size:
            self.request_timestamps.popleft()

        if len(self.request_timestamps) < self.limit:
            self.request_timestamps.append(current_time)
            return True
        else:
            return False

# Example Usage
limiter = SlidingWindowRateLimiter(limit=5, window_size=10)  # 5 requests in the last 10 seconds

for i in range(10):
    if limiter.allow_request():
        print(f"Request {i + 1} allowed.")
    else:
        print(f"Request {i + 1} denied.")
    time.sleep(1)

Sliding Window Counter

هذا المقال مخصص للأعضاء المنتسبين لخطط الاشتراك المدفوعة فقط

اشترك الآن بنشرة اقرأ-تِك الأسبوعية

لا تدع أي شيء يفوتك. واحصل على أحدث المقالات المميزة مباشرة إلى بريدك الإلكتروني وبشكل مجاني!