English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

invitado
1 / ?

Dos formas de soportar más carga

Bienvenido

Cuando un servicio comienza a ceder bajo la carga, el operador se enfrenta a una elección. Hacer la máquina existente más grande (más CPU, más RAM, discos más rápidos). O agregar más máquinas que cada una realice el mismo trabajo.

El primer camino se conoce como escalado vertical (scale up). El segundo se conoce como escalado horizontal (scale out).

Esta lección enseña por qué casi todas las arquitecturas web modernas eligen el escalado horizontal y qué propiedad de la carga de trabajo hace viable esa elección. La respuesta se esconde en una sola palabra: estado.

Al final entenderás:

- Las curvas de costos de la escalabilidad vertical frente a la horizontal y en qué casos cada una tiene sentido

- Qué significan en la práctica "con estado" (stateful) y "sin estado" (stateless), y por qué uno de ellos se multiplica de forma económica

- La matemática para dimensionar una flota de réplicas bajo carga esperada y de pico

- La regla de margen de capacidad (headroom) que impide que una capa colapse más allá del punto de inflexión de la cola

- Dónde debe residir el estado (nunca desaparece) y cómo extraerlo de las capas que necesitan escalar

Por qué la escalabilidad horizontal gana a partir de un umbral

Escalabilidad vertical: una caja más grande

Ventajas: simple. Sin cambios de código. Sin coordinación. El mismo proceso ahora tiene más CPU.

Desventajas: límite superior. La VM comercialmente disponible más grande tiene una RAM y un número de núcleos finitos. Por encima de eso, ningún dinero compra más capacidad. Los costos se vuelven superlineales más allá del punto óptimo de la oferta de un proveedor. Una falla de esa única máquina tumba todo el servicio.

Escalamiento Horizontal: Muchas Cajas Más Pequeñas

Ventajas: sin límite superior (hasta donde estés dispuesto a pagar y coordinar máquinas). La capacidad se suma linealmente con el número de réplicas, de manera predecible. Una falla de una sola réplica elimina 1/N de la capacidad, no el 100%.

Desventajas: requiere que la carga de trabajo lo soporte. Algunas cargas de trabajo (una base de datos grande única, un servidor de juego con estado que mantiene sesiones en vivo) resisten el escalamiento horizontal. La coordinación y la distribución de la carga se convierten en preocupaciones operativas.

El punto de cruce: cualquier servicio de producción que necesite sobrevivir a la falla de una sola máquina debe ejecutarse en al menos dos máquinas. Una vez que aceptas dos, ya has elegido el escalamiento horizontal. A partir de ahí, la pregunta no es "¿debemos hacerlo?" sino "¿cuán barato podemos agregar la siguiente réplica?"

El habilitador clave: una carga de trabajo que no mantiene estado por solicitud en la propia máquina. Entonces, cualquier réplica puede responder a cualquier solicitud, y agregar una réplica añade capacidad sin coordinación.

Escalamiento vertical vs horizontal: curva de costos y límite superior

Un equipo ejecuta un servicio en una única VM con 8 CPUs que maneja 800 solicitudes por segundo al 60% de uso de CPU. Esperan que el tráfico crezca 4 veces en el próximo año. Están debatiendo: ¿alquilar una VM de 32 CPUs (escalamiento vertical) o ejecutar cuatro VMs idénticas de 8 CPUs detrás de un balanceador de carga (escalamiento horizontal)? ¿Qué opción recomiendas y nombra dos razones que vayan más allá de la capacidad bruta?

Con estado vs. Sin estado en la práctica

El estado nunca desaparece, solo se desplaza

Componente con estado: retiene información cuya pérdida cambiaría el comportamiento. Una base de datos que almacena cuentas de usuarios. Una caché que guarda tokens de sesión. Un trabajador que fija una conexión de transmisión de larga duración a un usuario específico.

Componente sin estado: no retiene ninguna información cuya pérdida importaría. Un nivel web que lee una solicitud, consulta una base de datos y escribe una respuesta. Cada solicitud es independiente; el nivel no recuerda nada entre solicitudes.

Insight clave: el estado nunca desaparece de un sistema. Se desplaza a una capa diseñada para retenerlo (una base de datos, un clúster de Redis, un almacén de objetos). Las capas que reciben el tráfico pueden entonces ser sin estado, y las capas sin estado escalan horizontalmente porque cualquier réplica puede responder a cualquier solicitud.

Prueba práctica: si mataras aleatoriamente un proceso en esta capa y lo reiniciaras, ¿algún usuario experimentaría una respuesta incorrecta o una sesión perdida? Si es así, retiene estado. Si no, no lo hace.

Ejemplos

- Un proceso web de Python que lee solicitudes, consulta Postgres y devuelve JSON: sin estado. El estado reside en Postgres.

- Un proceso web de Python que mantiene los carritos de compra de los usuarios en la memoria local: con estado. Matar el proceso pierde los carritos.

- Un servidor WebSocket que mantiene abiertas las conexiones con los usuarios del chat: con estado en el sentido de conexión. Si se detiene el proceso, se pierden las conexiones; los clientes deben reconectarse. A menudo, estos aún pueden escalar horizontalmente con cuidado (sesiones pegajosas, hash consistente).

- Una caché Redis que actúa como fachada para Postgres: con estado para el contenido de la caché, pero aceptable si los fallos de caché (cache misses) son tolerables. Un fallo en una réplica significa un fallo de caché, no pérdida de datos.

Diseñar para escalado horizontal = mover el estado fuera de la capa que necesita escalar.

Auditar una capa sospechosa

Un equipo ejecuta una API de recomendaciones en 6 VMs de backend detrás de un proxy inverso. La aplicación: lee un ID de usuario de la solicitud, recupera la actividad reciente del usuario desde Postgres, ejecuta un algoritmo de puntuación y devuelve una lista de elementos recomendados. Dos comportamientos no estándar:

- La aplicación mantiene una caché de 'actividad reciente del usuario' en la memoria del proceso, que se pobla en la primera solicitud para un usuario y se reutiliza en solicitudes posteriores.

- La aplicación usa sesiones pegajosas (sticky sessions): una vez que un usuario accede a la VM #3, todas sus solicitudes posteriores van a la VM #3 (el proxy está configurado para enrutamiento pegajoso mediante una cookie).

Identifica cuál de estos dos comportamientos hace que la capa tenga estado y explica qué se rompería si el equipo intentara escalar de 6 VMs a 12. Luego, propone un rediseño que permita a la capa escalar horizontalmente sin perder el beneficio de la caché de usuario.

La fórmula de réplicas

La fórmula de capacidad más simple

Una vez que un nivel se vuelve sin estado, dimensionarlo se convierte en aritmética. Necesitas suficientes réplicas para que la carga en estado estable llegue y salga a la misma tasa, con margen para picos.

La fórmula:

réplicas = ⌈ (carga_pico × factor_de_pico) / capacidad_por_réplica ⌉ + margen

Donde:

- carga_pico: máximo de solicitudes por segundo sostenidas que esperas en la operación normal

- factor_de_pico: un multiplicador que cubre ráfagas breves por encima del pico (comúnmente 1.5x a 2x para tráfico predecible, 3x o más para viral / impredecible)

- capacidad_por_réplica: solicitudes por segundo que una réplica maneja con latencia y utilización aceptables (comúnmente medido al 70% de CPU, no en saturación)

- margen: réplicas adicionales para que algunas fallas de réplicas no colapsen el nivel (comúnmente 1-2 réplicas para flotas pequeñas, 10-20% para las más grandes)

Ejemplo resuelto: un backend maneja 100 req/s al 70% de CPU por réplica. La carga máxima es de 600 req/s. Se esperan picos ocasionales de 2x. Se desea sobrevivir a 2 fallos de réplicas.

réplicas = ⌈ (600 × 2) / 100 ⌉ + 2 = 12 + 2 = 14 réplicas

La regla del 80%

La capacidad por réplica no es el punto de saturación. Mida la capacidad al 70-80% de CPU, nunca al 100%.

Más allá de aproximadamente un 80% de utilización, las curvas de encolado suben bruscamente: una cola que se procesaba en 10 ms al 60% de utilización tarda 80 ms al 90% de utilización. La latencia, no el rendimiento, se rompe primero. (La lección complementaria geometry_of_stateless_horizontal_scaling deriva esta curva matemáticamente.)

Escalamiento automático frente a aprovisionamiento estático

Estático: aprovisionar para la carga máxima × margen de picos y aceptar el costo de operar con baja utilización fuera de las horas pico.

Escalamiento automático: un controlador agrega y elimina réplicas basándose en la utilización observada, la latencia objetivo o la profundidad de la cola.

Advertencia sobre el autoscaling: el tiempo de inicio en frío es importante. Si un nuevo réplica tarda 2 minutos en arrancar, el autoscaling no puede responder a un pico de 30 segundos. Un autoscaling maduro mantiene un pool cálido de réplicas preasignadas justo por debajo del umbral de escalado hacia arriba.

Fórmula de dimensionamiento de réplicas con ejemplo resuelto

Dimensionar una flota para un nuevo servicio

Tu equipo planea lanzar una API de metadatos de video. Las pruebas de rendimiento muestran que una sola réplica maneja 250 req/s con un 70% de CPU y una latencia p99 de 50 ms. El departamento de marketing pronostica una carga máxima de 4,000 req/s durante las horas pico. Un evento promocional planificado podría provocar un aumento temporal de 3 veces la carga máxima. Quieres que el servicio sobreviva a 3 fallas simultáneas de réplicas sin exceder el 80% de utilización en las réplicas restantes.

Aplica la fórmula de réplicas para dimensionar la flota de lanzamiento. Muestra tu trabajo paso a paso, y luego explica una razón por la cual tu número podría seguir siendo incorrecto (inicio en frío, calentamiento de caché, latencia de dependencias, lo que puedas defender).

Arranque en frío, drenado lento y otros bordes reales

Las flotas reales tienen bordes reales

La fórmula asume que las réplicas aparecen al instante, aceptan tráfico al instante y liberan tráfico al instante. Ninguna de esas afirmaciones se cumple en producción.

Arranque en frío: una nueva réplica necesita iniciar el sistema operativo, arrancar el proceso, cargar la configuración, calentar las cachés y pasar las comprobaciones de salud. Esto puede tardar desde 5 segundos (reinicio de contenedor) hasta 5 minutos (arranque completo de VM + descarga de imagen). El escalado automático no puede responder a picos más cortos que este retraso.

Drenado lento: una réplica que se está eliminando del grupo necesita tiempo para finalizar las solicitudes en curso antes de terminar. De lo contrario, los usuarios verán respuestas truncadas. Los proxies inversos admiten el drenado (dejar de aceptar nuevas solicitudes, finalizar las activas), pero esto toma de segundos a minutos.

Pool cálido: las flotas de producción mantienen un pool de réplicas preprovisionadas pero inactivas, listas para recibir tráfico ante una señal. Intercambia un pequeño costo constante por una respuesta rápida ante picos de demanda.

Drenado de conexiones vs. eliminación inmediata: el apagado elegante es importante. Un SIGTERM que activa el drenado tarda más que un SIGKILL, pero no interrumpe las solicitudes de los usuarios.

Ventana de verificación de salud: una réplica que acaba de iniciarse podría pasar su primera verificación de salud antes de que su pool de conexiones a la base de datos esté cálido; entonces, el proxy envía tráfico real y las primeras docena de solicitudes son lentas. Ajusta las verificaciones de salud para probar la ruta real, no solo la supervivencia del proceso.

Aumento de la adhesividad (stickiness): incluso las capas nominalmente sin estado adquieren adhesividad con el tiempo (cachés de CDN, cachés de resueltor DNS, pools de conexiones). Sé escéptico con las 'réplicas idénticas' que, sin embargo, se comportan de manera diferente.

¿Pool cálido o escalado automático reactivo?

Tu API de metadatos de video (la misma de la pregunta anterior, dimensionada con 51 réplicas para el pico estable + picos de demanda) experimenta un pico de 30 segundos hasta 5 veces la carga normal cada vez que se sube un nuevo video viral. Actualmente, el escalado automático tarda 90 segundos para añadir una nueva réplica desde frío (descarga de imagen + calentamiento). Durante ese intervalo de 90 segundos, la latencia aumenta bruscamente y algunas solicitudes caducan.

Propón una solución. Elige: (a) mantener el escalado automático reactivo pero ajustarlo de manera diferente, (b) provisionar un pool cálido de réplicas inactivas, o (c) provisionar estáticamente para el pico de 5x de forma permanente. Justifica tu elección y nombra un costo que impongan las otras dos opciones.

Diseña un Nivel Sin Estado Bajo Restricciones

Síntesis

Has aprendido por qué el escalado horizontal gana a partir de un umbral pequeño, qué significa el estado en la práctica, cómo dimensionar una flota bajo carga esperada y de pico, y dónde el escalado horizontal se rompe en los límites.

Aplica los cuatro.

Diseña un nivel de backend para feed.example.com, una API de feed social. Restricciones: capacidad por réplica de 200 req/s al 70% de CPU; carga pico esperada de 1500 req/s; factor de aumento (surge) de 2.5x (historias en tendencia ocasionales); sobrevivir a 2 fallas simultáneas de réplicas; tiempo de arranque en frío (cold-start) de 60 segundos; los picos pueden durar 45 segundos; el presupuesto permite cierta capacidad ociosa, pero no una provisión permanente de 2.5x.

Dimensiona la flota estable (muestra el cálculo), elige tu estrategia para manejar picos (pool cálido / autoescalado reactivo / ambos) e identifica una pieza de estado por usuario que la aplicación probablemente retenga y a dónde debe moverse para mantener el nivel sin estado (stateless).

Hacia dónde va este curso

Hacia dónde va este curso

Ahora tienes un modelo mental funcional de una capa sin estado: por qué escala, cómo dimensionarla, qué se rompe en sus límites y hacia dónde debe moverse el estado cuando la empujas más allá de la capa que necesita crecer.

La siguiente lección de este curso (cs_distsys_ingress_egress_separation) aborda un problema más sutil: incluso una capa sin estado perfectamente dimensionada puede fallar de maneras sorprendentes cuando el tráfico entrante y saliente comparten la misma ruta de red. El ejemplo clásico involucra a un proxy que intenta conectarse a sí mismo; la solución implica dividir una capa en dos con responsabilidades diferentes.

Lección complementaria: geometry_of_stateless_horizontal_scaling deriva la curva de encolado, la Ley de Little aplicada a una flota de réplicas y el significado geométrico de la rodilla de utilización del 80 %.

Buen trabajo. Adelante.