Rate limiting et throttling en Swift : protection et optimisation des API

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Votre API sous attaque : pourquoi le rate limiting et le throttling sont indispensables pour le développeur Swift

\n\n

Imaginez : vous avez lancé une superbe application en Swift, les utilisateurs sont ravis, les serveurs fonctionnent parfaitement. Mais soudainement, l'effondrement. Quelqu'un a lancé un script qui bombarde votre API avec des milliers de requêtes par seconde. Ou simplement un utilisateur actif spamme le bouton « Actualiser » plus vite que vous ne pouvez traiter les données. Résultat : des ralentissements, un crash du serveur et des avis négatifs.

\n\n

Cela vous parle ? Alors cet article est pour vous. Nous allons détailler le rate limiting et le throttling en Swift — des techniques qui sauveront votre backend et rendront votre application stable. Vous apprendrez comment implémenter la limitation des requêtes en Swift côté client, en utilisant des approches modernes avec async/await, et quels patterns fonctionnent réellement.

\n\n

Rate limiting vs Throttling : quelle est la différence ?

\n\n

Avant d'écrire du code, clarifions les termes. Beaucoup confondent ces concepts, bien qu'ils résolvent des problèmes différents.

\n\n

Rate limiting (limitation de débit)

\n

Il s'agit d'une limite stricte : « Pas plus de N requêtes par période ». Si la limite est dépassée, la requête est rejetée. Le serveur renvoie généralement un 429 Too Many Requests. Exemple : vous autorisez au maximum 100 requêtes par minute depuis une même adresse IP.

\n\n

Throttling (étranglement)

\n

C'est un mécanisme plus souple : les requêtes ne sont pas bloquées, mais mises en file d'attente et exécutées à une fréquence définie. Imaginez que votre API ne peut traiter que 5 requêtes par seconde. Le throttling les mettra en file d'attente et les enverra à la vitesse appropriée, sans surcharger le serveur.

\n\n

En Swift, les deux approches s'implémentent différemment. Examinons les meilleures pratiques.

\n\n

Implémentations pratiques du rate limiting en Swift

\n\n

1. Throttling simple avec timer (GCD)

\n\n

La façon la plus simple de limiter les requêtes en Swift est d'utiliser DispatchQueue et un timer. Voici un exemple qui garantit que les requêtes ne seront pas envoyées plus d'une fois par seconde :

\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("Requête rejetée : trop fréquente")\n            }\n        }\n    }\n}\n\n// Utilisation\nlet throttler = RequestThrottler(interval: 2.0)\nthrottler.performThrottledRequest {\n    // Votre requête API\n    print("Requête exécutée")\n}
\n\n

Cette approche est simple, mais pas idéale : elle rejette simplement les requêtes « en trop ». Pour de nombreux scénarios, cela suffit, mais si vous devez préserver l'ordre et garantir l'exécution, lisez la suite.

\n\n

2. Rate limiter avec file d'attente (async/await)

\n\n

Avec l'arrivée de Swift async/await, nous avons une manière élégante d'implémenter un swift rate limiter avec support de file d'attente. Voici à quoi cela ressemble :

\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                

Blogs

Book Recommendations