Limitación de velocidad y throttling en Swift: protección y optimización de API

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Su API bajo ataque: por qué la limitación de velocidad y el throttling son imprescindibles para el desarrollador Swift

\n\n

Imagine: lanzó una aplicación increíble en Swift, los usuarios están encantados, los servidores funcionan perfectamente. Pero de repente, el colapso. Alguien ejecutó un script que golpea su API con miles de solicitudes por segundo. O simplemente un usuario activo presiona el botón "Actualizar" más rápido de lo que usted puede procesar los datos. El resultado: lentitud, caída del servidor y reseñas negativas.

\n\n

¿Le suena familiar? Entonces este artículo es para usted. Analizaremos la limitación de velocidad y el throttling en Swift: técnicas que salvarán su backend y harán que la aplicación sea estable. Aprenderá cómo implementar la limitación de solicitudes en Swift del lado del cliente, utilizando enfoques modernos con async/await, y qué patrones realmente funcionan.

\n\n

Rate limiting vs Throttling: ¿cuál es la diferencia?

\n\n

Antes de escribir código, aclaremos los términos. Muchos confunden estos conceptos, aunque resuelven diferentes problemas.

\n\n

Rate limiting (limitación de velocidad)

\n

Es un límite estricto: "No más de N solicitudes por período". Si se excede el límite, la solicitud es rechazada. El servidor generalmente devuelve 429 Too Many Requests. Ejemplo: permite no más de 100 solicitudes por minuto desde una misma IP.

\n\n

Throttling (estrangulamiento)

\n

Es un mecanismo más suave: las solicitudes no se bloquean, sino que se ponen en cola y se ejecutan a una frecuencia determinada. Imagine que su API solo puede procesar 5 solicitudes por segundo. El throttling las pondrá en cola y las enviará a la velocidad necesaria, sin sobrecargar el servidor.

\n\n

En Swift, ambos enfoques se implementan de manera diferente. Veamos las mejores prácticas.

\n\n

Implementaciones prácticas de rate limiting en Swift

\n\n

1. Throttling simple con temporizador (GCD)

\n\n

La forma más sencilla de limitar solicitudes en Swift es usar DispatchQueue y un temporizador. Aquí hay un ejemplo que garantiza que las solicitudes se envíen no más de una vez por segundo:

\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("Solicitud rechazada: demasiado frecuente")\n            }\n        }\n    }\n}\n\n// Uso\nlet throttler = RequestThrottler(interval: 2.0)\nthrottler.performThrottledRequest {\n    // Su solicitud API\n    print("Solicitud ejecutada")\n}
\n\n

Este enfoque es simple, pero no ideal: simplemente descarta las solicitudes "sobrantes". Para muchos escenarios es suficiente, pero si necesita mantener el orden y garantizar la ejecución, siga leyendo.

\n\n

2. Rate limiter con cola (async/await)

\n\n

Con la llegada de Swift async/await tenemos una forma elegante de implementar un swift rate limiter con soporte de cola. Así es como se ve:

\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