Resultados Experimento 2 ‐ Escalabilidad del servicio de cotización - JuanHerreraP/Proyecto-MISO-Solventa-Grupo-11 GitHub Wiki
1. Objetivo del Experimento
Validar si la arquitectura actual basada en contenedores desplegados en AWS ECS Fargate puede soportar una rampa de carga masiva correspondiente al objetivo del ASR EC03:
- Throughput Objetivo: 50,000 peticiones/minuto (~834 req/s).
- Criterio de Latencia: p95 $\le 1.0$ segundo en respuestas exitosas.
- Criterio de Escalabilidad: Autoescalado dinámico de tareas hasta un máximo de 10 tareas.
- Tolerancia a Errores:
http_req_failed < 1%.
2. Setup del Experimento
2.1. Arquitectura Evaluada
- Topología: Microservicios co-ubicados en la misma definición de tarea (Task Definition) de AWS ECS Fargate, comunicados internamente vía
localhost:costo(Rating/Cotización - expuesto al ALB)perfilamiento(:8000)open-finance(:8001)open-data(:8002)
- Infraestructura:
- AWS ECS Fargate: Asignación inicial de 1 vCPU / 2 GB RAM por tarea.
- Application Load Balancer (ALB): Integrado con ECS Target Group para balanceo dinámico.
- Auto Scaling: Política basada en número de peticiones por destino (
ALBRequestCountPerTargetde 25).
- Stack de Aplicación:
- Framework: FastAPI
- Servidor ASGI: Uvicorn (
--workers 2,--backlog 2048) - Cliente HTTP Interno:
httpx.AsyncClientpersistente con reutilización de pool de sockets TCP.
2.2. Herramienta de Pruebas de Carga
- Herramienta:
k6 - Executor:
ramping-arrival-rate - Escenario:
- Rampa progresiva de 500 req/min (8.3 req/s) a 50,000 req/min (833.3 req/s) en un intervalo de 5 minutos y 30 segundos.
- Carga máxima simultánea: 3,000 VUs (Virtual Users).
3. Resultados Obtenidos
Desglose del Comportamiento del Sistema
-
Rendimiento de Procesamiento (Throughput vs. Carga Inyectada):
- Del total de 35,193 peticiones que el sistema alcanzó a recibir, solo 5,341 (15.17%) fueron procesadas exitosamente con respuestas HTTP 200/201.
- 29,852 peticiones (84.82%) finalizaron en error debido a timeouts de conexión y lectura (ReadTimeout) acumulados en la cadena de microservicios.
- El ejecutor de k6 reportó 165,490 iteraciones descartadas (
dropped_iterations), lo que indica que el sistema se congeló a tal punto que el cliente de pruebas no pudo seguir inyectando el tráfico planificado para la rampa.
-
Comportamiento de la Latencia:
- Peticiones Exitosas: Incluso el 15% de peticiones que lograron responder con éxito sufrieron una degradación severa, registrando una latencia media de 3.0s y un p95 de 11.22s (muy lejos del objetivo de $\le 1.0\text{s}$).
- Peticiones Fallidas / Global: El p90 y p95 global tocaron el techo de 1 minuto (
1m0s), que corresponde al tiempo máximo de espera configurado en el cliente HTTP antes de abortar la conexión.
4. Análisis de Causa Raíz
El análisis del comportamiento del clúster ante el pico de carga evidencia que el fallo masivo del experimento no se debió a un error puntual de software, sino a límites estructurales de la topología probada:
4.1. Acoplamiento Sincrónico en Cadena y Saturación de Event Loop
- Aunque se implementó
httpx.AsyncClientasíncrono y se ajustaron los workers de Uvicorn, la latencia acumulada de red inter-contenedor impuso un techo de procesamiento infranqueable de ~97 req/s (frente al objetivo de ~834 req/s). - Cada milisegundo de demora en los servicios secundarios mantuvo abiertas las conexiones HTTP principales, congelando el bucle de eventos (event loop) de FastAPI/Uvicorn y agotando rápidamente el backlog de peticiones.
4.2. Alcantado el Límite de Cuota de Infraestructura en AWS (Service Quotas)
- La política de autoescalado del servicio en ECS Fargate detectó el incremento de uso de CPU e intentó aprovisionar réplicas adicionales para absorber el tráfico.
- Sin embargo, el escalado se detuvo abruptamente en 10 tareas (la mitad del límite configurado de 20 tareas).
- La cuenta alcanzó el límite por defecto de vCPUs concurrentes de AWS Fargate (
Fargate On-Demand vCPU resource count), registrando en CloudWatch la falla de aprovisionamiento
4.3. Cascada de Timeouts y Degradación Total del Servicio (ReadTimeout)
- Al sobrepasar la capacidad de procesamiento de las 10 tareas disponibles y no poder escalar más por el límite de AWS, las peticiones entrantes acumularon tiempos de espera que superaron los umbrales de timeout.
- Los sockets colgados y no liberados consumieron la CPU y memoria de los contenedores activos, provocando respuestas masivas de fallo HTTP 5xx y rechazando más de 74,000 solicitudes.
5. Propuesta de Cambio de Arquitectura: Desacoplamiento con AWS SQS
Con el objetivo de erradicar la pérdida masiva de peticiones (84.82% de fallos por timeouts) y absorber picos de tráfico extremo sin incurrir en un sobredimensionamiento excesivo de recursos que generaría costos operativos insostenibles, se aprueba la transición hacia una Arquitectura Orientada a Eventos (EDA) respaldada por AWS SQS.
Este cambio estructural permite mantener una infraestructura base eficiente y costo-efectiva, evitando el sobredimensionamiento estático de vCPUs y memoria. La nueva arquitectura propuesta y su flujo de integración se pueden visualizar detalladamente en el diagrama de la vista de despliegue.