Rate Limiting in Swift: Begrenzung der Anforderungsrate für iOS und macOS

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Rate Limiting in Swift: Vollständige Anleitung für iOS- und macOS-Apps

\n\n

Rate Limiting (Begrenzung der Anforderungsrate) ist ein kritischer Mechanismus für den stabilen Betrieb von mobilen und Desktop-Anwendungen. Im Swift-Ökosystem (iOS/macOS) ermöglicht dieser Ansatz die Kontrolle der Anzahl von API-Aufrufen, E/A-Operationen oder beliebiger sich wiederholender Aktionen pro Zeiteinheit. Ohne Rate Limiting riskiert Ihre App, vom Server blockiert zu werden, Akkuladung durch endlose Wiederholungsversuche zu verschwenden oder übermäßige Netzlast zu erzeugen.

\n\n

Warum ist die Begrenzung der Anforderungsrate in Swift notwendig?

\n\n
    \n
  • Schutz vor Überschreitung von API-Limits — viele Server (z. B. GitHub, Twitter, Stripe) legen strenge Kontingente für die Anzahl der Anfragen pro Minute/Stunde fest.
  • \n
  • Leistungsoptimierung — Verhinderung eines "Aufruf-Sturms" bei schnellem Scrollen oder Animationen.
  • \n
  • Einsparung von Datenvolumen und Akku — besonders relevant für mobile Geräte.
  • \n
  • Einhaltung der App Store-Richtlinien — übermäßige Hintergrundanfragen können zur Ablehnung der App führen.
  • \n
\n\n

Grundlegende Ansätze zur Implementierung von Rate Limiting in Swift

\n\n

Betrachten wir drei grundlegende Muster, die ohne externe Bibliotheken implementiert werden können:

\n\n

1. Token-Bucket (Token Bucket)

\n

Klassischer Algorithmus, bei dem "Token" mit einer festen Rate hinzugefügt werden. Jede Anfrage verbraucht einen Token. Sind keine Token mehr vorhanden, wird die Anfrage abgelehnt.

\n\n
import Foundation\n\nfinal class TokenBucket {\n    private let capacity: Int\n    private var tokens: Int\n    private let refillRate: Double // Token pro Sekunde\n    private var lastRefill: Date\n    private let queue = DispatchQueue(label: "token.bucket.queue")\n    \n    init(capacity: Int, refillRate: Double) {\n        self.capacity = capacity\n        self.tokens = capacity\n        self.refillRate = refillRate\n        self.lastRefill = Date()\n    }\n    \n    func tryConsume() -> Bool {\n        queue.sync {\n            refill()\n            if tokens > 0 {\n                tokens -= 1\n                return true\n            }\n            return false\n        }\n    }\n    \n    private func refill() {\n        let now = Date()\n        let elapsed = now.timeIntervalSince(lastRefill)\n        let newTokens = Int(elapsed * refillRate)\n        if newTokens > 0 {\n            tokens = min(capacity, tokens + newTokens)\n            lastRefill = now\n        }\n    }\n}\n\n// Beispiel zur Verwendung\nlet limiter = TokenBucket(capacity: 10, refillRate: 2.0) // 10 Anfragen, 2 pro Sekunde\nif limiter.tryConsume() {\n    print("✅ Anfrage erlaubt")\n} else {\n    print("⛔️ Limit überschritten, warten")\n}
\n\n

2. Sliding Window (Gleitendes Fenster)

\n

Speichert die Zeitstempel der letzten N erfolgreichen Anfragen. Wenn das Fenster voll ist, werden neue Aufrufe blockiert.

\n\n
final class SlidingWindowLimiter {\n    private let maxRequests: Int\n    private let windowDuration: TimeInterval\n    private var timestamps: [Date] = []\n    private let queue = DispatchQueue(label: "sliding.window.queue")\n    \n    init(maxRequests: Int, windowDuration: TimeInterval = 60) {\n        self.maxRequests = maxRequests\n        self.windowDuration = windowDuration\n    }\n    \n    func canProceed() -> Bool {\n        queue.sync {\n            let now = Date()\n            // Entferne veraltete Zeitstempel\n            timestamps.removeAll { now.timeIntervalSince($0) > windowDuration }\n            \n            if timestamps.count < maxRequests {\n                timestamps.append(now)\n                return true\n            }\n            return false\n        }\n    }\n}\n\n// Beispiel: maximal 5 Anfragen in 10 Sekunden\nlet windowLimiter = SlidingWindowLimiter(maxRequests: 5, windowDuration: 10)
\n\n

3. Throttling mit DispatchQueue

\n

Verwendet integrierte GCD-Mechanismen zur erzwungenen Verzögerung

Empfehlungen