Pruebas de carga y perfiles de estrés
Resumen breve
Las pruebas de carga son pruebas de rendimiento y resiliencia del sistema bajo escenarios realistas y extremos. Base del éxito: modelo de tráfico correcto (abierto vs cerrado), SLO registrado, métrica pura (latency/throughput/error/saturación), datos representativos, automatización y repetibilidad. El resultado no es un «dígito RPS», sino una solución: dónde están los cuellos de botella, cuánto cuesta el rendimiento, dónde está el umbral de falla y cómo moverlo.
SLO/SLI y métricas de destino
SLO (ejemplo): p95 API ≤ 250 ms, p99 ≤ 600 ms; error ≤ 0. 3 %/30 días.
SLI: latency (p50/p95/p99), throughput (RPS/CPS/QPS), saturation (CPU/heap/GC/FD/conn), ошибки (5xx, timeouts), очереди (depth/lag), DB (locks, slow queries), кэш (hit-ratio).
Bujes de error y desencadenantes de saturación (por ejemplo, CPU> 75% o queue depth> X → degradación).
Tipos de pruebas
1. Baseline/Benchmark - servicio único/endpoint, condiciones «perfectas».
2. Load es un «día de trabajo» realista + ramp-up/ramp-down.
3. Stress - Aumentar la carga antes de la degradación y fijación de breakpoint.
4. Spike es un salto abrupto (x2-x10 en segundos/minutos).
5. Soak/Endurance es una carrera larga (8-72 h): fugas de memoria, deriva de latencia.
6. Capacity es una carga escalonada para construir una curva de rendimiento y planificar la capacidad.
7. Degradation/Chaos-mix - carga + fallos parciales (BD ralentizado, caída de caché, aplink «agarrado»).
Modelos de tráfico: Abierto vs Cerrado
Modelo abierto (más realista para Internet): los usuarios vienen con intensidad de λ (flujo similar a Poisson). Si el sistema frena, las peticiones se acumulan en lugar de «congelarse».
Modelo cerrado: número fijo de usuarios virtuales (VU) con think-time. Cuando aumenta la latencia, el RPS cae artificialmente, con cuidado con los hallazgos.
Recomendación: para API de primera línea, utilice el modelo abierto (k6 'arrival-rate'), para escenarios sincrónicos internos - combine con cerrado.
Perfiles de carga (plantillas)
«Día normal»: fondo básico + oscilaciones diurnas.
«Evento pico»: 10-30 min antes del inicio (calentamiento), spike abrupto al comienzo, meseta, cola.
«Torneo/Stream»: escalones de madera, picos repetidos en intervalos.
«Degradación de la infraestructura»: la mitad de la caché está vacía, una región está apagada, aumentando la latencia del PSP.
«Failover»: el tráfico fluye a la reserva más allá de 1-5 minutos; verificamos las tormentas de auto-skale/HPA/Retry.
Datos y preparación del entorno
Datos de prueba: cardenalito realista (proveedores, monedas, países), campos «sucios», asignaciones de consultas (Pareto/Zipf).
Secretos/PII: anonimización; claves/PSP - sandbox.
Entorno: soporte perf dedicado, aislamiento de integraciones (mock/stabs), versiones fijas.
Observabilidad: métricas (Prometheus), registros (Loki/ELK), pistas (OTel). Fijar build-id en las respuestas.
Anti-tormenta de retraídas e idempotencia
Retraídas sólo para operaciones idempotentes; apostar retry-budget (por ejemplo, ≤ 10% del tráfico).
Exponential backoff + jitter; «collapsing» de idénticos GET.
Para los pagos - claves idempotentes y estados explícitos.
Protección antirrobo: caché, SWR, semáforos locales.
Herramientas y patrones
k6 (scripting, open-model, buen reporting), Locust (Python-scripts), Gatling (Scala), JMeter (una amplia gama de protocolos).
Protocolos: HTTP/1. 1/2/3, gRPC, WebSocket, TCP/UDP; servidor push no pruebe «como GET».
Generación de tráfico: escala horizontal de generadores, control de cuello de botella de red.
Comamos perfiles: pprof/async-profiler/ebpf bajo carga, rutas OTel.
javascript import http from 'k6/http';
import {check, sleep} from 'k6';
export const options = {
scenarios: {
warmup: { executor: 'ramping-arrival-rate', startRate: 50, timeUnit: '1s',
preAllocatedVUs: 200, stages: [ { target: 200, duration: '5m' } ] },
spike: { executor: 'constant-arrival-rate', rate: 1200, timeUnit: '1s',
preAllocatedVUs: 2000, startTime: '6m', duration: '3m' }
},
thresholds: {
http_req_failed: ['rate<0. 3%'],
http_req_duration: ['p(95)<250', 'p(99)<600']
}
};
export default function () {
const res = http. get(`${__ENV. BASE_URL}/api/v1/catalog? c=${Math. floor(Math. random()1000)}`);
check(res, { 'status is 200': (r) => r. status === 200 });
sleep(Math. random()0. 9) ;//think time (for closed parts of the script)
}
Metodología
1. Hipótesis → qué cuellos de botella son probables (CPU, DB, caché, red, TLS, GC).
2. Perfil → escenarios/rutas, cuotas de tráfico, modelos (abierto/cerrado), datos.
3. Calentar → caché/connects/TLS/intérpretes.
4. Aumento de → escalones hasta la intensidad objetivo.
5. Meseta → recolección de métricas y pistas estables.
6. Estrés/descenso → encontrar el punto de fractura, observar el auto-skale.
7. Análisis → correlación de métricas, flamegraph, informe y plan de cambios.
8. Repruff → repetición a través de CI de paipeline (Regeneración Perf).
Análisis de resultados
Curva «carga → retraso/error»: buscamos la rodilla (capacity).
latencia breakdown: red (DNS/TLS/connect), proxy, aplicación, DB, llamadas externas.
Saturación: CPU> 75-85%, pausa GC> p95, espera I/O, cola de tareas.
Elasticidad: tiempo de reacción del scale automático (HPA/KEDA), «inicio en frío», calentamiento de caché.
Costo: $/1000 RPS para el SLO objetivo, previsión de presupuesto para el pico.
Prácticas
Indicadores de degradación: «colas» p99, aumento de colas, caída de hit-ratio, aumento de intentos de retraídas.
Excluye confaunders: límites de descriptores de archivos, sysctl, conn-pool, 'reuseport', cadena TLS, OCSP.
DB: índices/planes/caché de consultas, agrupación de conexiones, operaciones de batch, backpressure en los productores.
Caché: tamaño/eviction-policy, teclas de acceso rápido, replicación.
Red/edge: HTTP/2/3, resumption≥70%, Brotli, clave de caché CDN, tered-cache.
Observabilidad bajo carga
Métricas: sistema (CPU/amb/IO), runtime (GC/heap), red (RTT/loss/ECN), L7 (p95/99, 5xx/429), colas, clústeres de BD/caché.
Tracks: permite samplear en «colas» (tail-based), marcas build-id/canarios.
Logs: agregación de errores con límite de volumen (para que no sea «perDOSo» logs-pipeline).
Experimentos: características-flags y confecciones deben registrarse en el informe.
Automatización y CI/CD
Perf-jobs en CI (smoke 3-5 min, nightly 30-60 min, weekly soak).
Límites de tolerancia: latencia/errores/recursos → "rompemos el build' en caso de regresión.
Artefactos: gráficos, flamegraphs, perfiles, informes JSON (k6/jtl).
Versionar datos y secuencias de comandos, ruidos PR de scripts.
Características específicas para iGaming/Fintech
Torneos/partidos: spike + plateau; calentamiento TLS/DNS/CDN, límites de agrupación elevados, rutas «grises» para bots.
Pagos/PSP: límites de sandbox, idempotencia, tiempos de espera estrictos; comprobación degrade-mode (caché de referencia, colas).
Jackpots/eventos: atomicidad y consistencia, sin tomas, carga de RNG/leadboards.
Antifraude/AML: carga de reglas/puntuación ML, retroceso, deduplicación de eventos.
Regulación: lógica de métricas y versiones en picos, informes de auditoría.
Lista de comprobación de inicio
- Se han fijado SLO/SLI y «líneas rojas» (error/latencia/saturación).
- Los escenarios y perfiles de carga están aprobados (abierto/cerrado, spike/soak/stress).
- Los datos son realistas, PII camuflados, integraciones - sandbox/mock.
- La observabilidad está lista: métricas/tracks/logs, etiquetas de lanzamiento.
- Las configuraciones de sistemas (ulimit/sysctl/pools) están documentadas.
- El plan de auto-skale/caché de calefacción y los criterios de rollback.
- Alertas de umbral y plan de comunicación de comandos (on-call).
- Se ha preparado una plantilla de informes (gráficos, conclusiones, acciones).
Errores típicos
La prueba de modelo cerrado produce un resultado «verde» y el prodo cae (no se puede ignorar el modelo abierto).
Los datos no representativos (una moneda/un proveedor) → conclusiones falsas.
Preparación cero: cachés fríos/TLS/connects → latencia inflada al inicio.
Retiros sin límites → tormenta y caídas en cascada.
Los mismos perfiles para todos los servicios → saltarse los «puntos calientes» reales.
La ausencia de correas de soak → las fugas de memoria y la deriva no son visibles.
Resultados opacos: no hay rastros/flamgrafos → es imposible localizar el cuello de botella.
Minibuses
Definición del ancho de banda marginal (breakpoint)
1. Etapas de 10-20% de carga cada 5-10 minutos.2) Capturar el momento donde p95 crece bruscamente y errores> SLO. 3) Eliminamos los perfiles CPU/BD/caché. 4) Plan de optimización y repetición.
Freno a las tormentas de retraídas
1. Restringir el retry-budget y habilitar backoff + jitter. 2) Introduzca request-collapsing/SWR. 3) Permitir el «degrad-mode» (funcionalidad limitada). 4) Revisa de nuevo la idempotencia.
Pic-evento (torneo) - pre-plan
1. Calentar CDN/DNS/TLS/pools. 2) Aumentar el target HPA, cocine la reserva. 3) Límites de rate separados para bots. 4) Dashboards de «modo pico», puente de comunicación on-call.
Soak-noche
1. 8-12 horas de carga estable. 2) Monitorim heap/FD/conn/GC-pauses. 3) Probamos delta p95 y hit-ratio. 4) Registramos las fugas y la deriva.
Resultado
Las pruebas de carga son un proceso de toma de decisiones de ingeniería, no una «carrera por RPS». Modela perfiles reales (especialmente el modelo abierto), fija SLO, quita métricas y pistas, busca la rodilla de rendimiento y considera el costo de rendimiento. Automatice las corridas, mantenga los retoques anti-tormenta y planifique eventos de pico, por lo que la plataforma será predecible y sostenible en los momentos más tensos.