Resultados experimento 2 - galoryzen/equipo8-pfinal GitHub Wiki

Resultado del Experimento 2

Título del experimento

Validación de latencia en creación de reserva con comunicación síncrona Booking → Catalog bajo carga concurrente


Tabla de Contenidos


1. Objetivo del experimento

Validar que la táctica de comunicación síncrona HTTP entre Booking Service y Catalog Service, con control de concurrencia pesimista (SELECT FOR UPDATE) en PostgreSQL, cumple el SLA de latencia p95 < 1.5s para la creación de reserva bajo carga pico.

2. Hipótesis

Las tácticas y patrones arquitectónicos seleccionados para el flujo de reserva comunicación síncrona HTTP (estilo Llamado-Retorno) entre Booking y Catalog, control de concurrencia pesimista (SELECT FOR UPDATE) en PostgreSQL, limitación de tiempo de ejecución (timeout 500ms), e introducción de concurrencia (FastAPI async + connection pooling) son suficientes para mantener la latencia p95 por debajo de 1.5 segundos bajo carga pico.

El punto de sensibilidad identificado es la contención de locks a nivel de fila en inventory_calendar: bajo alta concurrencia, múltiples transacciones compiten por lockear las mismas filas, lo que podría degradar la latencia de forma no lineal. El experimento busca determinar si las tácticas elegidas mitigan este riesgo dentro de los escenarios de carga esperados.

3. Metodología

3.1 Infraestructura

El experimento se ejecutó sobre la infraestructura desplegada en AWS:

Componente Configuración
Booking Service ECS Fargate
Catalog Service ECS Fargate
PostgreSQL Amazon RDS (t3g.small)
Load Balancer AWS ALB
Service Discovery Cloud Map DNS (VPC interna)

3.2 Generador de carga

Se utilizó Locust ejecutado desde una máquina local contra el ALB público. Cada usuario simulado:

  1. Envía un POST /api/bookings/checkout-start con datos del catálogo seeded
  2. Espera un think time aleatorio de 1-3 segundos (simula comportamiento real)
  3. Repite durante toda la duración del escenario

3.3 Estrategia de contención

Para maximizar la contención de locks y poner a prueba el punto de sensibilidad:

  • Distribución HOT/COLD: 3 room_types (de 20 totales) reciben el 80% del tráfico. Esto concentra los SELECT FOR UPDATE en pocas filas de inventory_calendar.
  • Overlap de fechas: un pool de 4 fechas de check-in con estancias de 2 noches genera solapamiento en las filas lockeadas (ej: check-in 03-01 lockea filas 03-01 y 03-02; check-in 03-02 lockea filas 03-02 y 03-03 la fila 03-02 es compartida).
  • Inventario suficiente: 10,000 unidades por room_type/día para evitar agotamiento de inventario durante la prueba y medir contención pura de locks.

3.4 Escenarios de carga

Escenario Usuarios concurrentes Spawn rate Duración
Normal 10 2/s 3 min
Moderado 25 5/s 3 min
Pico 50 10/s 3 min
Alta contención 100 20/s 3 min

Entre cada escenario se realizó un reset completo de la base de datos (drop schemas + init + seed) para garantizar condiciones iniciales idénticas.

3.5 Clasificación de respuestas

Código Significado Clasificación
201 Reserva creada exitosamente Éxito
409 Sin inventario disponible Fallo funcional (esperado)
504 Timeout de Booking → Catalog (> 500ms) Fallo de latencia
502 Error interno de Catalog Fallo de infraestructura

4. Resultados

4.1 Tabla resumen

Escenario Requests Fallos Tasa de error RPS p50 p95 p99 p99.9 Max
10 usuarios 856 0 0.00% 4.78 91ms 110ms 200ms 380ms 384ms
25 usuarios 2,114 0 0.00% 11.79 92ms 120ms 240ms 380ms 382ms
50 usuarios 4,253 0 0.00% 23.71 93ms 130ms 320ms 540ms 646ms
100 usuarios 8,420 121 1.44% 46.92 94ms 260ms 730ms 1,100ms 1,394ms

4.2 Desglose de errores (escenario 100 usuarios)

Tipo de error Cantidad Porcentaje
504 Timeout (Catalog > 500ms) 121 1.44%
409 No inventory 0 0%
502 Error de Catalog 0 0%

4.3 Evaluación de las tácticas

Las tácticas arquitectónicas seleccionadas permiten cumplir el SLA p95 < 1.5s en todos los escenarios.

Escenario p95 Cumple SLA Margen
10 usuarios 110ms SI 13.6x
25 usuarios 120ms SI 12.5x
50 usuarios 130ms SI 11.5x
100 usuarios 260ms SI 5.8x

Incluso en el escenario más agresivo (100 usuarios concurrentes, ~47 RPS), el p95 de 260ms está 5.8 veces por debajo del límite de 1.5 segundos. Esto demuestra que la combinación de tácticas elegidas no solo cumple el SLA, sino que proporciona un margen amplio que absorbe la variabilidad operacional.

5. Análisis de los resultados

5.1 Comportamiento de la latencia mediana (p50)

La mediana se mantuvo prácticamente constante entre 91ms y 94ms a través de los 4 escenarios. Esto indica que el request típico no se ve afectado por el nivel de concurrencia: la mayoría de las solicitudes adquieren el lock rápido y completan sin espera significativa.

5.2 Degradación no lineal en la cola de latencia

La degradación de latencia se concentra en los percentiles altos y crece de forma no lineal:

  • p95: creció linealmente de 110ms a 260ms (2.4x) al multiplicar los usuarios por 10x
  • p99: creció de 200ms a 730ms (3.7x)
  • p99.9: creció de 380ms a 1,100ms (2.9x)
  • Max: creció de 384ms a 1,394ms (3.6x)

Este patrón es la firma clásica de la contención de locks a nivel de fila: la mayoría de requests pasan rápido, pero los que se encolan detrás de múltiples transacciones experimentan esperas que crecen exponencialmente con la profundidad de la cola.

5.3 Los 504 timeouts confirman el punto de sensibilidad

Las 121 fallas en el escenario de 100 usuarios fueron todas de tipo 504 (timeout). Esto significa que la llamada HTTP de Booking a Catalog excedió los 500ms configurados como timeout (CATALOG_TIMEOUT_SECONDS = 0.5). En estos casos, la espera del lock en PostgreSQL fue la causa directa.

Es importante notar que el timeout actúa como un mecanismo de protección: impide que un request lento mantenga una conexión ocupada indefinidamente y evita que la degradación se propague al rest del sistema. Los requests que superaron 500ms fueron cortados y el cliente recibió una respuesta rápida de error, en lugar de quedar esperando.

6. Contextualización de la carga

Para una cadena hotelera con 5 propiedades (como la del experimento), los escenarios representan:

Escenario Usuarios RPS Equivalente en reservas/hora Representa
Normal 10 ~5 ~18,000 Operación diaria típica
Moderado 25 ~12 ~43,000 Horas pico
Pico 50 ~24 ~86,000 Evento de alta demanda (temporada alta)
Alta contención 100 ~47 ~170,000 Stress test / punto de quiebre

Considerando que una cadena de 5 hoteles podría procesar entre 500 y 2,000 reservas diarias, incluso el escenario de 10 usuarios ya supera la demanda realista por un amplio margen. El escenario de 100 usuarios es un stress test diseñado para identificar los límites del sistema.

7. Conclusiones

7.1 La hipótesis se valida, las tácticas arquitectónicas son adecuadas

Las tácticas y patrones seleccionados demuestran ser suficientes para cumplir el SLA bajo todos los niveles de carga probados:

  • Comunicación síncrona HTTP (Llamado-Retorno): el salto de red Booking → Catalog vía Cloud Map DNS (~1ms) es despreciable. La simplicidad del patrón síncrono se justifica para esta escala.
  • Concurrencia pesimista (SELECT FOR UPDATE): garantiza consistencia fuerte del inventario. La contención de locks es medible pero se mantiene dentro del SLA incluso bajo stress test (p95 = 260ms, 5.8x de margen).
  • Limitar tiempo de ejecución (timeout 500ms): las 121 fallas 504 en el escenario de 100 usuarios demuestran que el timeout funciona como mecanismo de protección, evitando que la degradación se propague.
  • Introducir concurrencia (async + connection pooling): el throughput por usuario se mantuvo constante (~0.47 RPS/usuario) sin degradación, confirmando que el modelo async escala linealmente.

7.2 El punto de sensibilidad se confirmó pero no compromete las tácticas

La contención de locks existe: el p99 crece 3.7x (200ms → 730ms) de 10 a 100 usuarios, mientras el p50 apenas se mueve (91ms → 94ms). Sin embargo, este efecto solo se manifiesta más allá del p95 y bajo carga (100 usuarios, ~47 RPS) que excede la demanda realista de 5 hoteles (~500-2,000 reservas/día).

8. Impacto en la arquitectura propuesta

No se requieren cambios en la arquitectura. Las tácticas evaluadas, comunicación síncrona, concurrencia pesimista, timeout, y async con connection pooling, son adecuadas para la escala de operación esperada.

9. Evidencias

9.1 Video de Evidencias

El video de evidencias lo pueden encontrar en el siguiente enlace: Video de Evidencias del Experimento 2

9.2 Reportes de Locust (HTML)

Cada escenario generó un reporte HTML interactivo con gráficas de latencia, throughput y distribución de tiempos de respuesta:

Escenario Reporte
10 usuarios scenario_10.html
25 usuarios scenario_25.html
50 usuarios scenario_50.html
100 usuarios scenario_100.html

9.3 Datos crudos (CSV)

Los datos completos de cada escenario están disponibles en formato CSV para análisis adicional:

Archivo Contenido
scenario_N_stats.csv Percentiles (p50, p95, p99), RPS, tasa de fallos
scenario_N_stats_history.csv Serie temporal segundo a segundo (para gráficas)
scenario_N_failures.csv Detalle de cada tipo de fallo y su frecuencia

Todos los archivos se encuentran en el directorio experimento2/results/.

9.4 Código fuente del experimento

Componente Ruta
Booking Service services/booking/app/
Catalog Service services/catalog/app/
Esquema de BD db/init.sql
Datos de prueba db/seed.sql
Locustfile locustfile.py
Script de ejecución scripts/run_experiments.sh
Docker Compose (local) docker-compose.yml
Infraestructura AWS terraform/