El planteamiento y cuándo aplica esta pregunta
Un servicio de pedidos tiene una capacidad sostenible comprobada mediante pruebas de carga de 3,000 solicitudes por segundo con una latencia p99 de 250 ms. Durante una promoción, las llegadas aumentan a 8,000 solicitudes por segundo. Una dependencia de inventario se ralentiza, el número de solicitudes en curso (in-flight) y la antigüedad de la cola aumentan, los clientes reintentan y el escalado automático necesita tres minutos antes de que las nuevas instancias estén listas. Los envíos de pedidos críticos, las verificaciones interactivas de disponibilidad y la conciliación por lotes interna comparten el servicio.
Diseña una política de protección contra sobrecargas que mantenga el proceso receptivo y preserve la mayor cantidad posible de trabajo útil. Explica las señales de detección, los límites de concurrencia y de colas, el control de admisión, la prioridad de las solicitudes, la degradación elegante, el comportamiento de los reintentos, la recuperación y la validación. Las cifras son supuestos de entrevista, no una afirmación sobre un sistema de producción en particular.
Esta es una pregunta de backend porque la decisión central es cómo un servicio protege su CPU, memoria, hilos, conexiones y llamadas subsiguientes (downstream). Un limitador de tasa (rate limiter) distribuido aplica la política de tráfico entre inquilinos (tenants) o ventanas de tiempo; esta pregunta comienza después de que el tráfico permitido sigue siendo mayor que la capacidad actual del servicio. Los tiempos de espera (timeouts), los reintentos y los disyuntores (circuit breakers) protegen las llamadas a dependencias individuales, mientras que el control de sobrecarga decide qué nuevo trabajo puede permitirse admitir el servicio.
Qué evalúa el entrevistador
Una respuesta sólida identifica la saturación a partir del trabajo local, no solo de la tasa de solicitudes. Un umbral fijo de solicitudes por segundo falla cuando una solicitud se vuelve cinco veces más costosa o cuando la ralentización de una dependencia retiene las conexiones por más tiempo. El trabajo en curso, la antigüedad de la cola, los espacios disponibles de trabajadores o conexiones, la CPU, la presión de memoria y el margen del tiempo límite (deadline slack) exponen el recurso que realmente se está agotando.
La siguiente señal es un sistema acotado. Las colas ilimitadas convierten el exceso de demanda en crecimiento de memoria y solicitudes obsoletas. El candidato debe limitar el trabajo concurrente en el cuello de botella, mantener la cola pequeña o eliminarla, y rechazar a bajo costo antes de realizar un análisis (parsing) costoso o llamadas subsiguientes. El objetivo es el trabajo útil y exitoso, no aceptar todas las solicitudes ni maximizar los intentos brutos.
El entrevistador también busca una política consciente del negocio. Los envíos de pedidos críticos pueden recibir una cuota reservada; las comprobaciones de disponibilidad pueden utilizar una caché de corta duración; la conciliación por lotes puede pausarse. La prioridad aún requiere equidad por inquilino para que un solo cliente grande no consuma todos los espacios reservados. Finalmente, el diseño necesita un bucle de recuperación cerrado: suprimir la amplificación de reintentos, escalar como una respuesta de capacidad más lenta, restablecer la admisión gradualmente y probar la ruta degradada antes de un incidente.
Preguntas para aclarar antes de responder
- ¿Qué recurso se satura primero? La saturación de CPU favorece un límite local de concurrencia o costo. Una dependencia lenta exige un mamparo (bulkhead) separado de conexión/concurrencia. El crecimiento de la memoria o la antigüedad de la cola pueden requerir una cola más pequeña y un rechazo más temprano. Cada cuello de botella cambia la señal de admisión.
- ¿Qué operaciones son esenciales y cuáles se pueden degradar? Aquí, enviar un pedido es crítico, la disponibilidad puede tolerar datos ligeramente obsoletos y la conciliación por lotes puede pausarse. Si legalmente se requiere que cada operación use inventario actualizado, el respaldo en caché no es válido y un fallo explícito es más seguro.
- ¿Cuál es el tiempo límite (deadline) de extremo a extremo? El tiempo en cola consume el mismo límite de tiempo que la ejecución. El servicio debe descartar el trabajo que ya no puede completarse y propagar la cancelación hacia los servicios subsiguientes.
- ¿Son las solicitudes igualmente costosas? Un solo token por solicitud funciona solo cuando los costos son similares. Los endpoints costosos pueden necesitar permisos ponderados o grupos separados para que el trabajo crítico de bajo costo no quede atrapado detrás de trabajos por lotes costosos.
- ¿Pueden los clientes reintentar de forma segura? Una lectura rechazada puede reintentarse más tarde. Una escritura de pedido necesita una clave de idempotencia y una búsqueda del resultado. El servicio debe distinguir entre "reintentar más tarde" y "no reintentar", y todas las capas deben compartir un presupuesto de reintentos (retry budget).
- ¿Está disponible el desvío de tráfico? La conmutación por error (failover) a una región saludable puede absorber trabajo solo si el destino tiene capacidad disponible verificada. Mover la sobrecarga a ciegas puede generar una segunda falla.
Estructura de respuesta de 30 segundos
"Protegería el cuello de botella con un pequeño bucle cerrado. Primero, utilizaría pruebas de carga para establecer límites de concurrencia y de cola por instancia, y luego monitorearía el trabajo local en curso, la antigüedad de la cola, la CPU, la memoria, los grupos de conexiones y los plazos de tiempo restantes. Cuando aumente la saturación, rechazaría nuevo trabajo antes del procesamiento costoso, reservaría capacidad para el envío de pedidos, preservaría la equidad dentro de cada prioridad, serviría una respuesta en caché aprobada para la disponibilidad y pausaría el trabajo por lotes. Los rechazos utilizan una respuesta clara de sobrecarga temporal, mientras que los clientes reintentan solo operaciones idempotentes con retroceso exponencial (backoff), fluctuación aleatoria (jitter) y un presupuesto de reintentos compartido. El escalado automático agrega capacidad, pero es demasiado lento para ser la primera defensa. Me recuperaría con histéresis y un aumento gradual de admisión, para luego verificar la memoria acotada, el rendimiento útil, el éxito crítico, la equidad, la amplificación de reintentos y la recuperación mediante pruebas de sobrecarga".
Análisis detallado paso a paso
Comienza con una envolvente de capacidad medida. La cifra de 3,000 solicitudes por segundo es válida únicamente para la combinación de solicitudes probada, la latencia de dependencias, el recuento de instancias y el objetivo de latencia p99 de 250 ms. Registra el trabajo en curso correspondiente por instancia, la CPU, la memoria, la utilización de trabajadores y el uso de conexiones subsiguientes. La tasa de solicitudes es una entrada; la decisión de admisión debe seguir al recurso más cercano a fallar. Por ejemplo, cuando el inventario se ralentiza, la misma tasa de llegada crea más llamadas en curso, por lo que un controlador basado únicamente en la tasa reacciona demasiado tarde.
Establece límites de concurrencia independientes alrededor de los recursos escasos. El manejador de pedidos necesita un límite general, mientras que las llamadas de inventario y los trabajos por lotes obtienen mamparos (bulkheads) más pequeños. Se adquiere un permiso antes de asignar trabajo costoso y se libera en caso de éxito, falla, tiempo de espera o cancelación. Si los costos de las solicitudes difieren sustancialmente, utiliza permisos ponderados o grupos de endpoints separados. Un límite codificado de forma fija (hard-coded) es un punto de partida seguro a partir de pruebas de carga; un límite adaptativo puede mejorar la utilización, pero requiere retroalimentación estable, salvaguardas y una reversión (rollback) rápida.
Mantén las colas explícitas y acotadas. Una cola corta puede absorber una ráfaga conocida, pero su límite debe provenir del margen del tiempo límite (deadline slack) en lugar de la memoria disponible. Rechaza cuando la cola esté llena o cuando el retraso estimado en cola deje muy poco tiempo para terminar. Una cola ilimitada no puede crear capacidad; aumenta la latencia de cola (tail latency), retiene memoria y hace que los clientes reintenten solicitudes que ya están esperando. Monitorea tanto la profundidad de la cola como la antigüedad del elemento más antiguo, porque una cola pequeña de trabajo costoso aún puede estar obsoleta.
El control de admisión debe fallar de forma económica y consistente. En la puerta de enlace (gateway), aplica cuotas contractuales de inquilinos y límites de tráfico generales. En cada instancia de servicio, utiliza la saturación local para proteger la tarea propietaria del recurso. Si un microservicio subsiguiente está sobrecargado, rechaza río arriba (upstream) antes de realizar trabajo que se descartará más tarde. Transmite la criticidad de la solicitud a lo largo de la ruta de llamada para que el mismo pedido no sea admitido por una capa y rechazado aleatoriamente tras consumir trabajo en otra.
Utiliza una política de prioridades con reservas de capacidad explícitas:
| Clase | Acción ante sobrecarga | Razón |
|---|---|---|
| Envío de pedidos | Concurrencia reservada; rechazar solo tras superar su propio límite | Preserva la ruta crítica sin conceder capacidad ilimitada |
| Verificación de disponibilidad | Preferir datos en caché de corta duración con un contrato de frescura visible; de lo contrario, rechazar | Reduce el trabajo subsiguiente sin inventar una respuesta |
| Conciliación por lotes | Pausar la ingesta y reanudar más tarde a partir del progreso persistido | El trabajo es importante pero no requiere un plazo de tiempo interactivo |
La prioridad sin equidad puede dejar sin recursos a los inquilinos pequeños. Aplica cuotas de inquilinos o una programación justa dentro de una clase, y mantén una cuota mínima para el tráfico de recuperación o control. Evita decenas de niveles de prioridad: los operadores deben poder predecir qué solicitud se admite durante un incidente.
Cuando se alcance el límite, responde antes de realizar trabajo en la base de datos o dependencias. HTTP 503 representa una sobrecarga temporal y puede incluir Retry-After; no otorga permiso para que todos los clientes reintenten simultáneamente. Los clientes utilizan un retroceso exponencial limitado con fluctuación (jitter), un tiempo límite y un presupuesto de reintentos. Reintenta en una sola capa adecuada en lugar de en todas las capas. La creación de pedidos reutiliza una clave de idempotencia y consulta el resultado anterior tras un tiempo de espera ambiguo. Las solicitudes cuyo tiempo límite del emisor haya expirado se cancelan para que el servidor no complete trabajo inútil.
La degradación elegante reduce el costo en lugar de simplemente rechazar. La disponibilidad puede omitir el enriquecimiento opcional o utilizar una caché de antigüedad limitada si el contrato del producto lo permite. Los consumidores de lotes pueden dejar de extraer mensajes. Un mecanismo de respaldo que reporte existencias obsoletas como actuales es deshonesto; cuando la frescura es obligatoria, devuelve un resultado explícito de no disponible. Ejercita la degradación continuamente en una pequeña fracción del tráfico, ya que es probable que una ruta de emergencia no utilizada falle cuando se necesite.
El escalado automático, el desbordamiento regional y los aumentos de capacidad siguen siendo útiles, pero operan después del control de admisión. Escalar según el recuento bruto de solicitudes puede agregar instancias durante tráfico liviano y retrasarse durante tráfico costoso; incluye concurrencia, antigüedad de la cola o saturación de recursos. Las nuevas instancias deben calentar las conexiones antes de recibir una porción completa de carga. La conmutación por error necesita una comprobación de capacidad de destino. Ninguno de los dos mecanismos justifica eliminar los límites locales.
La recuperación utiliza un umbral de salida más bajo que el umbral de entrada. Después de que el trabajo en curso, la antigüedad de la cola y la salud de las dependencias permanezcan por debajo de ese umbral durante un período de retención, aumenta la carga admitida por pasos. Mantén las reservas de prioridad hasta que la latencia normal se estabilice. Esta histéresis y aumento gradual evitan que el sistema oscile entre estados abiertos y sobrecargados, o que inunde una dependencia que solo se ha recuperado parcialmente.
Valida la política más allá de la prueba de capacidad nominal. Reproduce la combinación de costos de solicitudes de producción y luego aumenta las llegadas de 3,000 a 8,000 solicitudes por segundo mientras ralentizas el inventario y retrasas el escalado automático durante tres minutos. Agrega reintentos sincronizados de clientes, un inquilino abusivo, plazos vencidos y la recuperación de la dependencia. Valida colas y memoria acotadas, uso estable de trabajadores y conexiones, rechazo económico, éxito de pedidos dentro de su reserva, equidad entre inquilinos, degradación honesta, amplificación de reintentos controlada y un retorno gradual a la normalidad. Mide las operaciones útiles completadas por separado de las solicitudes aceptadas y los intentos subsiguientes.
Ejemplo de respuesta de alta calidad
"Los 3,000 pedidos por segundo sostenibles son el resultado de una prueba de carga para una combinación de solicitudes específica, por lo que primero identificaría el recurso en ese límite. Durante la ralentización del inventario, las llamadas en curso y la ocupación de conexiones son más útiles que la tasa de solicitudes. Establecería un límite de concurrencia probado por instancia para el servicio, un mamparo (bulkhead) más pequeño para el inventario y una cola pequeña cuya espera aún encaje en el tiempo límite de la solicitud. Una vez alcanzado cualquiera de los límites, el servicio rechaza antes de realizar trabajo costoso.
Clasificaría el tráfico en envío de pedidos, disponibilidad y conciliación. Los pedidos reciben capacidad reservada pero aún tienen un límite estricto. La disponibilidad puede usar una caché de corta duración solo si la API expone ese contrato de frescura. La conciliación se pausa y se reanuda a partir del progreso persistido. Dentro de cada clase aplicaría equidad entre inquilinos, de modo que un solo cliente no pueda acaparar toda la reserva. También propagaría la prioridad hacia los servicios subsiguientes para evitar gastar trabajo en una solicitud que un servicio posterior descartará aleatoriamente.
La sobrecarga temporal devuelve un 503 reconocible y, cuando podamos estimarlo, Retry-After. Los clientes aún necesitan retroceso limitado, fluctuación (jitter), tiempos límite y un presupuesto de reintentos compartido. Solo una capa reintenta, y las escrituras de pedidos reutilizan una clave de idempotencia. Las llamadas expiradas cancelan el trabajo subsiguiente.
El escalado automático es el bucle de capacidad más lento porque las instancias necesitan tres minutos. Escalaría en función de señales de saturación y calentaría las nuevas instancias, mientras que el control de admisión local mantiene viva la flota existente. La recuperación requiere umbrales de salida más bajos y un aumento gradual.
La prueba definitiva es una prueba de sobrecarga a 8,000 solicitudes por segundo con inventario lento, escalado retrasado, reintentos, costos de solicitud mixtos y un inquilino ruidoso. Espero memoria y colas acotadas, un rendimiento útil estable, la reserva y equidad de pedidos prometidas, rechazos de bajo costo, sin tormentas de reintentos y una recuperación controlada una vez que el inventario se restablezca".
Errores comunes
- Aumentar el límite de la cola hasta que desaparezcan los errores → Las solicitudes aceptadas esperan más tiempo, consumen memoria, expiran y desencadenan reintentos sin agregar capacidad de ejecución → Acotar la cola a partir del margen del tiempo límite y rechazar temprano.
- Detectar la sobrecarga únicamente a partir de las solicitudes por segundo → El costo de las solicitudes y la latencia de las dependencias cambian, por lo que la misma tasa puede ser segura o catastrófica → Utilizar el trabajo local en curso, la antigüedad de la cola, la saturación de recursos y los grupos de dependencias.
- Dejar que el escalado automático sea la primera defensa → El retraso de tres minutos permite que las colas y los reintentos desestabilicen la flota actual → Mantener límites de admisión locales y luego escalar para restaurar el margen.
- Dar prioridad ilimitada al tráfico crítico → Puede agotar el mismo recurso y dejar sin capacidad al trabajo de recuperación → Reservar capacidad pero conservar un límite estricto y la equidad.
- Descartar carga aleatoriamente en cada microservicio → El trabajo aguas arriba se consume antes de un rechazo aleatorio posterior, lo que reduce el éxito útil de extremo a extremo → Propagar la criticidad y rechazar tan pronto como se conozca el cuello de botella.
- Devolver 503 y dejar que todos los clientes reintenten → Los reintentos sincronizados multiplican el exceso de carga → Usar fluctuación (jitter), tiempos límite, una sola capa de reintentos y un presupuesto de reintentos.
- Servir una respuesta de respaldo obsoleta sin marcar → El sistema parece disponible mientras viola la semántica del inventario → Exponer el contrato de frescura o fallar explícitamente.
- Restaurar el tráfico completo inmediatamente → La dependencia en recuperación se sobrecarga nuevamente → Usar histéresis, sondeos acotados y un aumento gradual de la admisión.
- Monitorear solo el tráfico aceptado → Una alta tasa de aceptación puede ocultar tiempos de espera, trabajo desperdiciado y reintentos → Medir las finalizaciones útiles, el costo de rechazo, el tiempo límite desperdiciado y la amplificación de intentos.
Preguntas de seguimiento y respuestas
Pregunta de seguimiento 1: ¿Por qué no resolver esto con un limitador de tasa distribuido?
Un limitador de tasa distribuido es útil para cuotas contractuales, control de abusos y modelado de tráfico antes de que las solicitudes lleguen al servicio. No puede observar por sí mismo que la latencia del inventario ha aumentado el costo de cada solicitud permitida. Mantén el límite en la puerta de enlace (gateway) y luego agrega protección local de concurrencia y colas en el propietario del recurso. Si los costos de las solicitudes son estables y el servicio tiene un solo cuello de botella, un límite de tasa conservador puede ser la solución suficiente y más simple.
Pregunta de seguimiento 2: ¿Cómo elegirías el límite de concurrencia?
Comienza a partir de una prueba de carga que utilice la combinación de solicitudes de producción y encuentra la concurrencia más alta que aún cumpla con los objetivos de latencia y recursos con margen disponible. Repítelo con la ralentización de la dependencia. Una relación en estado estable entre concurrencia, rendimiento y tiempo puede servir como verificación de coherencia, pero no garantiza capacidad ante llegadas en ráfagas o costos mixtos. Despliega el límite en modo de solo observación, realiza un despliegue canario (canary) del rechazo y luego aplica la restricción; revísalo cuando cambien el código, el tamaño de la instancia o las dependencias.
Pregunta de seguimiento 3: ¿Qué pasa si el 90% del tráfico está marcado como crítico?
Entonces la etiqueta ya no toma una decisión de admisión útil. Define la criticidad a partir de las operaciones comerciales, autentica quién puede establecerla, limita cada clase y reserva solo una porción medida. Dentro de la clase crítica, utiliza equidad de inquilinos o una prioridad estable por usuario para que la sobrecarga no favorezca arbitrariamente al cliente más ruidoso. Si la demanda verdaderamente crítica excede la capacidad física, parte del trabajo crítico aún debe fallar; el contrato debe establecer cómo.
Pregunta de seguimiento 4: ¿Podría la concurrencia adaptativa mejorar el diseño?
Puede seguir los cambios en el tiempo de servicio más de cerca que un límite estático, pero la latencia ruidosa y la retroalimentación retrasada pueden causar oscilaciones o descartes falsos. Comienza con el límite estático probado. Agrega control adaptativo solo con límites mínimos y máximos, señales suavizadas, histéresis, un valor de respaldo estable y pruebas de reproducción que cubran un deterioro rápido y una recuperación lenta.
Pregunta de seguimiento 5: ¿Dónde debería ocurrir el descarte de carga (load shedding) en un árbol de llamadas profundo?
El propietario del recurso necesita una última línea de defensa local. Una vez que ese servicio señala sobrecarga, las capas aguas arriba deben detener el trabajo antes y preservar la misma decisión de criticidad a lo largo de la ruta de llamada. Descartar solo en el borde (edge) carece de un estado preciso aguas abajo; descartar solo en la hoja desperdicia trabajo aguas arriba. El diseño práctico combina una política general en el borde, protección local y una señal de sobrecarga sobre la cual los emisores aguas arriba puedan actuar.
Pregunta de seguimiento 6: ¿Qué métricas de producción muestran que la política está funcionando?
Monitorea las finalizaciones útiles y la latencia por operación y prioridad; solicitudes admitidas, en cola, degradadas y rechazadas; la antigüedad de la cola más vieja; trabajo en curso; saturación de CPU, memoria, trabajadores y conexiones; trabajo con tiempo límite expirado; equidad por inquilino; intentos físicos por solicitud lógica; retraso de preparación del escalado automático; y tiempo transcurrido en modo de sobrecarga. Alerta ante la pérdida de reserva crítica, sobrecarga sostenida, costo de rechazo que se acerque al costo de una solicitud normal o una rampa de recuperación que retroceda repetidamente.