تحديد معدل الطلبات (Rate Limiting) والتحكم في التدفق (Throttling) في Swift: حماية وتحسين API

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

API الخاص بك تحت الهجوم: لماذا يعتبر تحديد معدل الطلبات والتحكم في التدفق أمرًا ضروريًا لمطور Swift

\n\n

تخيل: لقد أطلقت تطبيقًا رائعًا بلغة Swift، المستخدمون سعداء، الخوادم تعمل بشكل مثالي. ولكن فجأة - انهيار. شخص ما قام بتشغيل سكريبت يضرب API الخاص بك بآلاف الطلبات في الثانية. أو مجرد مستخدم نشط يضغط على زر "تحديث" أسرع مما يمكنك معالجة البيانات. النتيجة - بطء، انهيار الخادم وتقييمات سلبية.

\n\n

هل هذا مألوف؟ إذن هذه المقالة لك. سنشرح تحديد معدل الطلبات والتحكم في التدفق في Swift - تقنيات ستنقذ خادمك الخلفي وتجعل التطبيق مستقرًا. ستتعلم كيفية تنفيذ تقييد الطلبات في Swift على جانب العميل باستخدام أساليب حديثة مع async/await، وأي الأنماط تعمل حقًا.

\n\n

تحديد معدل الطلبات مقابل التحكم في التدفق: ما الفرق؟

\n\n

قبل كتابة الكود، دعنا نفهم المصطلحات. كثيرون يخلطون بين هذه المفاهيم، على الرغم من أنها تحل مشاكل مختلفة.

\n\n

تحديد معدل الطلبات (Rate limiting)

\n

هو حد صارم: "لا يزيد عن N طلب في الفترة الزمنية". إذا تم تجاوز الحد - يتم رفض الطلب. عادةً ما يعيد الخادم 429 Too Many Requests. مثال: تسمح بما لا يزيد عن 100 طلب في الدقيقة من عنوان IP واحد.

\n\n

التحكم في التدفق (Throttling)

\n

هي آلية أكثر مرونة: لا يتم حظر الطلبات، بل توضع في قائمة انتظار وتنفذ بتردد محدد. تخيل أن API الخاص بك يمكنه معالجة 5 طلبات فقط في الثانية. سيقوم التحكم في التدفق بترتيبها في قائمة انتظار وإرسالها بالسرعة المطلوبة، دون تحميل الخادم الزائد.

\n\n

في Swift، يتم تنفيذ كلا النهجين بشكل مختلف. دعنا نلقي نظرة على أفضل الممارسات.

\n\n

تطبيقات عملية لتحديد معدل الطلبات في Swift

\n\n

1. التحكم في التدفق البسيط باستخدام المؤقت (GCD)

\n\n

أبسط طريقة لتقييد الطلبات في Swift هي استخدام DispatchQueue ومؤقت. إليك مثال يضمن إرسال الطلبات بما لا يزيد عن مرة واحدة في الثانية:

\n\n
import Foundation\n\nfinal class RequestThrottler {\n    private let queue = DispatchQueue(label: "com.app.throttle")\n    private var lastRequestTime: Date = .distantPast\n    private let minimumInterval: TimeInterval\n    \n    init(interval: TimeInterval = 1.0) {\n        self.minimumInterval = interval\n    }\n    \n    func performThrottledRequest(block: @escaping () -> Void) {\n        queue.sync {\n            let now = Date()\n            if now.timeIntervalSince(lastRequestTime) >= minimumInterval {\n                lastRequestTime = now\n                DispatchQueue.main.async {\n                    block()\n                }\n            } else {\n                print("تم رفض الطلب: متكرر جدًا")\n            }\n        }\n    }\n}\n\n// الاستخدام\nlet throttler = RequestThrottler(interval: 2.0)\nthrottler.performThrottledRequest {\n    // طلب API الخاص بك\n    print("تم تنفيذ الطلب")\n}
\n\n

هذا النهج بسيط، لكنه ليس مثاليًا: فهو ببساطة يتجاهل الطلبات "الزائدة". بالنسبة للعديد من السيناريوهات، هذا كافٍ، ولكن إذا كنت بحاجة إلى الحفاظ على الترتيب وضمان التنفيذ - تابع القراءة.

\n\n

2. محدد المعدل مع قائمة انتظار (async/await)

\n\n

مع ظهور Swift async/await حصلنا على طريقة أنيقة لتنفيذ محدد المعدل في Swift مع دعم قائمة الانتظار. إليك كيف يبدو ذلك:

\n\n
import Foundation\n\nactor RateLimiter {\n    private let maxRequests: Int\n    private let perSecond: Double\n    private var requestTimestamps: [Date] = []\n    private var pendingTasks: [CheckedContinuation] = []\n    private var isProcessing = false\n    \n    init(maxRequests: Int, perSecond: Double) {\n        self.maxRequests = maxRequests\n        self.perSecond = perSecond\n    }\n    \n    func waitForSlot() async throws {\n        try await withCheckedThrowingContinuation { continuation in\n            pendingTasks.append(continuation)\n            if                

المدونات

توصيات الكتب