Servidor o aplicación: cómo se mide el cuello de botella
El tiempo hasta el primer byte en cada salto, los contadores de margen en la máquina y el slow log agrupado por frame bloqueante sitúan un sitio lento en una capa antes de que cambie nada.
En este artículo 7 secciones
- Mida el tiempo hasta el primer byte en cada salto: a través del edge, directo al origen y en localhost. El mayor hueco entre dos cifras adyacentes es la capa dueña de la latencia.
- Lea el margen de la máquina mientras está lenta: CPU idle y steal, memoria disponible, await de disco y profundidad de cola. Margen en todas partes bajo un sitio lento significa que la restricción está por encima del hardware.
- Dentro de la capa de aplicación, agregue: peticiones por URL, peticiones lentas por su frame bloqueante, consultas por digest. Cada agregación colapsa miles de líneas en una lista corta y ordenada con uno o dos nombres en lo alto.
Tiempo hasta el primer byte en cada salto
Las teorías sobre un sitio lento se forman con facilidad y se zanjan con dificultad. Tres mediciones las zanjan. Tome el tiempo hasta el primer byte a través del edge público, otra vez directamente contra el origen saltándose el edge, y otra vez en el host de la aplicación contra localhost. La diferencia entre dos lecturas adyacentes es el coste de esa capa.
# through the edge
curl -s -o /dev/null -w 'dns=%{time_namelookup} tls=%{time_appconnect} ttfb=%{time_starttransfer}\n' https://site.example/
# direct to the origin, edge bypassed
curl -s -o /dev/null -w 'ttfb=%{time_starttransfer}\n' --resolve site.example:443:ORIGIN_IP https://site.example/
# on the host, nothing in front of the application
curl -s -o /dev/null -w 'ttfb=%{time_starttransfer}\n' http://127.0.0.1/Lo que queda en localhost es la aplicación y los servicios a los que llama. La capa con el mayor hueco es adonde va el resto del trabajo.
Margen mientras duele
Lea los contadores durante el período lento, no después.
vmstat 1 5 # r (run queue), wa (I/O wait), st (steal), id (idle)
iostat -x 1 5 # await and aqu-sz per device
free -m # the available column, not usedUna run queue larga con poco idle es una máquina limitada por CPU. Un I/O wait alto con await alto en el dispositivo es storage. El steal es un vecino en un hipervisor compartido llevándose ciclos que el guest quería. CPU ociosa, memoria disponible y dispositivos con await bajo debajo de un sitio lento significan que la máquina espera algo que no es suyo: una llamada externa, un lock, una consulta lenta por razones distintas del hardware. Añadir hardware en ese punto produce una máquina más ociosa que sigue lenta.
Hay una tercera categoría entre las dos, y es frecuente: el pool. La página de status de PHP-FPM muestra una listen queue. Una cola de peticiones en espera con CPU ociosa significa que todos los workers están ocupados, normalmente bloqueados en la misma llamada lenta, y el sitio es lento por un techo de configuración y no por un techo de recursos. La misma forma aparece como un pool de conexiones a la base de datos saturado o como una cola de backend llena en HAProxy. La máquina es inocente y el código aún no ha sido condenado. El tamaño del pool y la llamada a la que espera son las dos lecturas siguientes.
Lea el tráfico antes que el código
El access log dice qué clase de problema es este. Encuentre primero el log por vhost. El log por defecto puede contener una pequeña fracción del tráfico real, y un recuento sobre el archivo equivocado da una respuesta equivocada con toda seguridad.
tail -n 100000 access.log | awk -F'"' '{print $2}' | sort | uniq -c | sort -rn | headUnas pocas URL repetidas miles de veces son el sitio llamándose a sí mismo, y la solución es una cache delante de esas URL. Peticiones que avanzan en el orden del sitemap son un crawler, y la solución es un rate limit. Una subida amplia y uniforme en muchas URL es demanda, y la solución es capacidad.
Colapse el slow log y el log de consultas
Un slow log es un montón de stack traces hasta que se indexa. Active el slow log de PHP-FPM con un umbral que capture las peticiones de las que se quejan los usuarios, después agrupe cada trace por el frame en el que quedó bloqueado, la hoja, y cuente. La lista ordenada es corta y en lo alto suele haber una llamada externa o una consulta.
En el lado de la base de datos, ordene por digest, no por plan. La parametrización inconsistente parte una consulta lógica en muchos planes que parecen inofensivos uno a uno. Sumado por digest, el verdadero dueño del tiempo de la base de datos se reensambla en una sola fila.
-- MySQL and Percona: by statement digest
SELECT digest_text, count_star, sum_timer_wait
FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC
LIMIT 10;
-- SQL Server: by query hash
SELECT query_hash, COUNT(*) AS plans, SUM(total_worker_time) AS cpu
FROM sys.dm_exec_query_stats
GROUP BY query_hash
ORDER BY cpu DESC;Antes de escribir cualquier índice, verifique el recuento real de filas y los índices que ya existen. Un índice en una tabla que no lo necesita es una ruta de escritura más lenta.
Lea la fuente primaria, no una historia plausible
| La historia | La fuente que la zanja |
|---|---|
| Se cayó, se quedó sin memoria | dmesg, journalctl --list-boots, last -x reboot: ¿reinició, y por qué? |
| La base de datos está corrupta | el propio error log de la base de datos, con grep de mensajes de crash y corrupción |
| Un proceso descontrolado se come la CPU | ps --forest y /proc/<pid>/cmdline: su identidad real y su padre, no un nombre plausible |
| Vemos errores de integridad | ethtool -S en la interfaz: cero errores de cable significa que el problema está por encima del cable |
| SELinux lo está bloqueando | ausearch -m avc -ts recent encadenado a audit2why: la denegación, con nombre, con el módulo de política que la corrige |
Cada fila sustituye una teoría por una lectura. La última importa en un sistema en enforcing: el log de auditoría responde a la pregunta sin cambiar la postura de seguridad para hacerla.
Demuéstrelo, después verifique con la misma medición
La correlación da un sospechoso. Una perturbación pequeña y reversible lo condena: detenga las consultas sospechosas durante unos segundos y observe si la carga se rellena. Si se rellena de inmediato, el tráfico en vivo es el motor y la solución pertenece al edge, delante de las peticiones que no deberían llegar siquiera a la base de datos. Hasta que se conoce la causa, el sistema es de solo lectura. Cuando la solución está puesta, se verifica con la medición que encontró el problema: si el tiempo hasta el primer byte por salto lo localizó, el tiempo hasta el primer byte por salto confirma que ha desaparecido.
Qué arreglamos y qué devolvemos
| En el edge, el mismo día | En su código, con el cambio exacto |
|---|---|
| Micro-caching con request collapsing delante de las URL calientes | Mover la llamada sincrónica a terceros a un job en segundo plano con timeout y fallback |
| Pools de workers y buffers dimensionados a la carga medida | Eliminar el bucle de render o el bucle de reintentos |
| Un covering index añadido en línea | Caducar los datos de aplicación que crecen sin límite |
| Reintentos y timeouts de HAProxy ajustados, un contexto SELinux corregido | Recortar el payload y los scripts enviados al navegador |
No cambiamos su código. Nombramos la línea, mostramos la medición que la señala y mantenemos el sitio en marcha mientras usted la corrige.
Respuestas directas
¿Cómo sé si lo que está lento es mi servidor o mi aplicación?+
Lea el margen durante el período lento: CPU idle y steal, memoria disponible, await de disco. Si los tres tienen holgura, la restricción está por encima del hardware, en la aplicación o en un servicio al que llama. El tiempo hasta el primer byte en localhost comparado con el edge confirma qué capa.
¿Cómo encuentran una consulta lenta en la base de datos?+
Ordenamos por digest, no por plan handle, para que una consulta lógica con muchas parametrizaciones muestre su coste total en una fila. Después verificamos recuentos de filas e índices existentes antes de escribir ningún DDL.
¿Pueden distinguir un bot de un pico de tráfico real?+
Desde el access log, por frecuencia de URL. Un puñado de URL repetidas miles de veces es el sitio llamándose a sí mismo, el orden del sitemap es un crawler, una subida amplia es demanda. Cada uno recibe una solución distinta.
¿Cambian mi código?+
No. Lo que está en el lado de la infraestructura lo arreglamos en el edge el mismo día, de forma reversible. Lo que está en su código lo devolvemos como el cambio exacto, con la medición que lo justifica.
Su sitio es lento y nadie se pone de acuerdo en por qué.
Hable con un ingeniero que mide cada salto antes de tocar nada.
Hable con un ingenieroHa llegado al final.
Ponga la lectura a trabajar
¿Qué está ejecutando?
Cuéntenos la carga de trabajo, el tráfico y los requisitos de recuperación. Empiece por el configurador de servidores o repase los detalles con un ingeniero.
Escrito por los ingenieros que construyen y operan la infraestructura que describe.Hable con un ingeniero
