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 واحد.
التحكم في التدفق (Throttling)
\nهي آلية أكثر مرونة: لا يتم حظر الطلبات، بل توضع في قائمة انتظار وتنفذ بتردد محدد. تخيل أن API الخاص بك يمكنه معالجة 5 طلبات فقط في الثانية. سيقوم التحكم في التدفق بترتيبها في قائمة انتظار وإرسالها بالسرعة المطلوبة، دون تحميل الخادم الزائد.
\n\nفي Swift، يتم تنفيذ كلا النهجين بشكل مختلف. دعنا نلقي نظرة على أفضل الممارسات.
\n\nتطبيقات عملية لتحديد معدل الطلبات في Swift
\n\n1. التحكم في التدفق البسيط باستخدام المؤقت (GCD)
\n\nأبسط طريقة لتقييد الطلبات في Swift هي استخدام DispatchQueue ومؤقت. إليك مثال يضمن إرسال الطلبات بما لا يزيد عن مرة واحدة في الثانية:
\n\nimport 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\n2. محدد المعدل مع قائمة انتظار (async/await)
\n\nمع ظهور Swift async/await حصلنا على طريقة أنيقة لتنفيذ محدد المعدل في Swift مع دعم قائمة الانتظار. إليك كيف يبدو ذلك:
\n\nimport 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