Probando K6
Necesitaremos algunas herramientas para probar y según he leído k6 hace cosas bastante interesantes, mejor que el viejo ab y que wrk que es mejor que ab, aunque yo los veo iguales.
Instrucciones de instalación: Install k6
No voy a hablar de k6 ni explicar, hay mil sitios para ver información incluso la documentación oficial.
Solo el motivo por el cual usar k6:
- Peticiones aleatorias a distintas urls
- Puede cortar conexión y reportar error si pasa de X ms
En mi caso, el servidor comenzó a flaquear con más +1500 peticiones peticiones simultaneas aunque no nos quedamos sin RAM
Lo interesante de k6 es que no manda 5000 peticiones "de una vez" puede hacerlo, pero se puede configurar para que mande de 0 a 5000 poco a poco, se mantenga X cantidad de tiempo en lo máximo ej 30 segundos recibiendo 5000 peticiones y luego empieza a bajar lentamente el número de peticiones.
Esto es un lujo, ver como las peticiones suben, ver cuando empieza a resentirse ej 1500 peticiones empieza a dar errores.
Luego cuando empieza a bajar vemos cuando empieza a recuperar que no debería ser en 1500 si tenemos overload igual empieza a recuperar cuando lleguen 500 o no recuperar nunca.
Esos detalles nos dan una idea, de como actuar, que pulir o directamente decidir si parar el la web antes de que muera completamente.
Resultados con la configuración base del servidor, prueba al limite 5000 peticiones
█ THRESHOLDS
http_req_duration
✗ 'p(95)<500' p(95)=28.25s
█ TOTAL RESULTS
checks_total.......: 297516 744.586193/s
checks_succeeded...: 66.26% 197150 out of 297516
checks_failed......: 33.73% 100366 out of 297516
✗ status es 200
↳ 96% — ✓ 144263 / ✗ 4495
✗ tiempo de respuesta < 200ms
↳ 35% — ✓ 52887 / ✗ 95871
HTTP
http_req_duration..............: avg=4.23s min=0s med=245.48ms max=1m0s p(90)=9.04s p(95)=28.25s
{ expected_response:true }...: avg=2.64s min=110.35ms med=242.08ms max=59.97s p(90)=5.93s p(95)=14.63s
http_req_failed................: 3.02% 4495 out of 148758
http_reqs......................: 148758 372.293097/s
EXECUTION
iteration_duration.............: avg=6.34s min=1.11s med=2.69s max=1m3s p(90)=11.61s p(95)=31.04s
iterations.....................: 148692 372.12792/s
vus............................: 4 min=4 max=5000
vus_max........................: 5000 min=5000 max=5000
NETWORK
data_received..................: 2.3 GB 5.7 MB/s
data_sent......................: 25 MB 62 kB/s
running (6m39.6s), 0000/5000 VUs, 148692 complete and 506 interrupted iterations
default ✓ [======================================] 0000/5000 VUs 6m10s
ERRO[0399] thresholds on metrics 'http_req_duration' have been crossedEstaba claro que el servidor no iba a aguantar ni 500 peticiones simultaneas a urls aleatorias, 1 core y 512 MB de RAM, a donde vamos, pero ahora tocara cachear en algún lado pero no creo que aguante más, no aguanto ni teniendo a cloudflare en medio, que me da que hizo by pass de todo
Luego haremos test más realiastas e iremos subiendo a ver donde se reciente el servidor realmente
Realmente se atendieron muchas peticiones, lo que pasa es que el 95% de las peticiones tardaron 30 segundos, o sea respuesta hubo y sinceramente simplemente pensé que moriría y ya.
Veamos a donde puede llegar nginx con un poco de tuning, que nos de respuestas de menos de 1 segundo pero se mantenga estable.
Me gustaría mostrar gráfica con apachetop pero consume como 100 MB de RAM y muere, apenas hay RAM para mantener la web online cuando se hacen 200 peticiones.
En cuanto a configuración lo interesante es esto:
export const options = {
stages: [
{ duration: '300s', target: 1200 }, // de 0 a 1200 usuarios en 300s
{ duration: '1m', target: 1200 }, //Mantener 1200 usuarios durante 1 minuto
{ duration: '10s', target: 0 }, //bajar de los 1200 a 0 en 10 segundos
],
thresholds: {
http_req_duration: ['p(95)<500'], // El 95% de las peticiones debe bajar de 500ms
},
};
Con 1200 en vez de 5000 la cosa cambia un poco, el test dura poco más de 6 minutos, los 300 segundos ( 5 min ) que tarda en llegar a 1200 + 1 minuto que se queda con 1200 peticiones y luego el tiempo que tarda en bajar.
Sin duda una herramienta interesante, tengo que investigar más sobre el potencial y a ver que pruebas podemos hacer con ello.
Tocará reservar 5 o 10 mb de cache para nginx y a ver si así el test va mejor.
Con unas mejoras en nginx aguanto perfecto los 1200, tanto en tiempo de respuesta como el servidor, no llego al limite de memoria, nos quedamos con 28 MB de RAM libres.
95% de las peticiones a 5 urls aleatorios ( solo 5 si, ya que no tenemos más aún jeje ) cargaron en menos de 500ms
/\ Grafana /‾‾/
/\ / \ |\ __ / /
/ \/ \ | |/ / / ‾‾\
/ \ | ( | (‾) |
/ __________ \ |_|\_\ \_____/
execution: local
script: test.js
output: -
scenarios: (100.00%) 1 scenario, 1200 max VUs, 6m40s max duration (incl. graceful stop):
* default: Up to 1200 looping VUs for 6m10s over 3 stages (gracefulRampDown: 30s, gracefulStop: 30s)
█ THRESHOLDS
http_req_duration
✗ 'p(95)<500' p(95)=895.36ms
█ TOTAL RESULTS
checks_total.......: 227626 611.294666/s
checks_succeeded...: 77.38% 176152 out of 227626
checks_failed......: 22.61% 51474 out of 227626
✓ status es 200
✗ tiempo de respuesta < 200ms
↳ 54% — ✓ 62339 / ✗ 51474
HTTP
http_req_duration..............: avg=274.26ms min=112.65ms med=180.71ms max=14.39s p(90)=543.73ms p(95)=895.36ms
{ expected_response:true }...: avg=274.26ms min=112.65ms med=180.71ms max=14.39s p(90)=543.73ms p(95)=895.36ms
http_req_failed................: 0.00% 0 out of 113813
http_reqs......................: 113813 305.647333/s
EXECUTION
iteration_duration.............: avg=2.27s min=1.11s med=2.26s max=17.18s p(90)=3.07s p(95)=3.21s
iterations.....................: 113813 305.647333/s
vus............................: 12 min=4 max=1200
vus_max........................: 1200 min=1200 max=1200
NETWORK
data_received..................: 1.7 GB 4.6 MB/s
data_sent......................: 14 MB 37 kB/s
running (6m12.4s), 0000/1200 VUs, 113813 complete and 0 interrupted iterations
default ✓ [======================================] 0000/1200 VUs 6m10s
ERRO[0372] thresholds on metrics 'http_req_duration' have been crossed Nada mal, para un blog ligero trabajando con 512 MB de RAM.
Otro día profundizo en esto, solo quería probar un poco el k6, pero tendremos que hacer tests más serios, mostrando configuración, uso de CPU, RAM y demás
He usado este script para testear:
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
stages: [
{ duration: '300s', target: 1500 }, // de 0 a 1500 usuarios en 300s
{ duration: '1m', target: 600 }, // Mantener 600 usuarios durante 1 minuto
{ duration: '10s', target: 0 }, // En 10 segundos bajamos de 1500 a 0
],
thresholds: {
http_req_duration: ['p(95)<500'], // El 95% de las peticiones debe bajar de 500ms
},
};
const URLS = [
'https://skamasle.com/',
'https://skamasle.com/blog-en-500ms-y-ecomerce-en-12-puede-que-no-salga-bien.html',
'https://skamasle.com/https-cuando-la-publicidad-de-los-medios-lo-hace-inseguro.html',
'https://skamasle.com/muchas-landings-en-un-servidor-pequeno-kits-digital-y-cuando-nada-sale-bien.html',
];
export default function () {
const url = URLS[Math.floor(Math.random() * URLS.length)];
const res = http.get(url);
check(res, {
'status es 200': (r) => r.status === 200,
'tiempo de respuesta < 200ms': (r) => r.timings.duration < 200,
});
sleep(Math.random() * 2 + 1);
}