Servidor ou aplicação: como medir o bottleneck
O tempo até ao primeiro byte em cada salto, os contadores de margem na máquina e um slow log agrupado por blocking frame situam um website lento numa camada antes de se mudar o que quer que seja.
Neste artigo 7 secções
- Meça o tempo até ao primeiro byte em cada salto: através do edge, diretamente no origin, e em localhost. O maior intervalo entre dois números adjacentes é a camada que detém a latência.
- Leia a margem da máquina enquanto está lenta: CPU idle e steal, memória disponível, await do disco e profundidade da fila. Margem em todo o lado por baixo de um website lento significa que a restrição está acima do hardware.
- Dentro da camada da aplicação, agregue: pedidos por URL, pedidos lentos pelo seu blocking frame, queries por digest. Cada um condensa milhares de linhas numa lista curta e ordenada com um ou dois nomes no topo.
Tempo até ao primeiro byte em cada salto
As teorias sobre um website lento formam-se facilmente e fecham-se com dificuldade. Três medições fecham-nas. Meça o tempo até ao primeiro byte através do edge público, de novo diretamente contra o origin com o edge contornado, e de novo no host da aplicação contra localhost. A diferença entre duas leituras adjacentes é o custo dessa camada.
# 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/O que resta em localhost é a aplicação e os serviços que ela chama. A camada com o maior intervalo é para onde vai o resto do trabalho.
Margem enquanto dói
Leia os contadores durante o período lento, não depois.
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 usedUma run queue longa com idle baixo é uma máquina limitada pela CPU. I/O wait alto com await alto no dispositivo é storage. Steal é um vizinho num hypervisor partilhado a levar ciclos que o guest queria. CPU idle, memória disponível e dispositivos com await baixo por baixo de um website lento significam que a máquina está à espera de algo que não lhe pertence: uma chamada externa, um lock, uma query lenta por razões que não o hardware. Acrescentar hardware nesse ponto produz uma máquina mais ociosa que continua lenta.
Há uma terceira categoria entre as duas, e é comum: o pool. A página de status do PHP-FPM mostra uma listen queue. Uma fila de pedidos à espera com a CPU idle significa que todos os workers estão ocupados, normalmente bloqueados na mesma chamada lenta, e o website está lento por causa de um teto de configuração e não de um teto de recursos. A mesma forma aparece como um connection pool de base de dados saturado ou uma fila de backend cheia no HAProxy. A máquina está inocente e o código ainda não foi condenado. O tamanho do pool e a chamada pela qual espera são as duas leituras seguintes.
Leia o tráfego antes do código
O access log diz que tipo de problema é este. Encontre primeiro o log por vhost. O log por omissão pode conter uma pequena fração do tráfego real, e uma contagem sobre o ficheiro errado dá uma resposta errada com toda a confiança.
tail -n 100000 access.log | awk -F'"' '{print $2}' | sort | uniq -c | sort -rn | headAlguns URL repetidos milhares de vezes é o website a chamar-se a si próprio, e a solução é uma cache à frente desses URL. Pedidos a avançar pela ordem do sitemap são um crawler, e a solução é um rate limit. Uma subida ampla e uniforme em muitos URL é procura, e a solução é capacidade.
Condense o slow log e o query log
Um slow log é uma pilha de stack traces até ser agrupado. Ative o slow log do PHP-FPM com um limiar que apanhe os pedidos de que os utilizadores se queixam, depois agrupe cada trace pelo frame em que ficou bloqueado, a folha, e conte. A lista ordenada é curta e no topo está normalmente uma chamada externa ou uma query.
Do lado da base de dados, ordene por digest, não por plano. A parametrização inconsistente divide uma query lógica em muitos planos que parecem inofensivos cada um por si. Somado por digest, o verdadeiro dono do tempo da base de dados volta a juntar-se numa única linha.
-- 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 escrever qualquer índice, verifique a contagem real de linhas e os índices que já existem. Um índice numa tabela que não precisa dele é um caminho de escrita mais lento.
Leia a fonte primária, não uma história plausível
| A história | A fonte que a fecha |
|---|---|
| Foi abaixo, ficou sem memória | dmesg, journalctl --list-boots, last -x reboot: reiniciou, e porquê |
| A base de dados está corrompida | o próprio error log da base de dados, com grep por mensagens de crash e corrupção |
| Um processo descontrolado está a comer a CPU | ps --forest e /proc/<pid>/cmdline: a sua verdadeira identidade e o seu pai, não um nome plausível |
| Estamos a ver erros de integridade | ethtool -S na interface: zero erros no cabo significa que o problema está acima do cabo |
| O SELinux está a bloqueá-lo | ausearch -m avc -ts recent encaminhado para audit2why: a negação, com nome, com o policy module que a corrige |
Cada linha substitui uma teoria por uma leitura. A última conta num sistema em enforcing: o audit log responde à pergunta sem alterar a postura de segurança para a fazer.
Prove, depois verifique com a mesma medição
A correlação dá um suspeito. Uma perturbação pequena e reversível condena-o: pare as queries suspeitas durante alguns segundos e observe se o load volta a encher. Se encher de imediato, o tráfego em produção é o fator e a solução pertence ao edge, à frente dos pedidos que nem sequer deviam chegar à base de dados. Até a causa ser conhecida, o sistema é só de leitura. Quando a correção entra, é verificada com a medição que encontrou o problema: se o tempo até ao primeiro byte por salto o localizou, o tempo até ao primeiro byte por salto confirma que desapareceu.
O que corrigimos e o que devolvemos
| No edge, no próprio dia | No seu código, com a alteração exata |
|---|---|
| Micro-caching com request collapsing à frente dos URL quentes | Mover a chamada síncrona a terceiros para um job em segundo plano com timeout e fallback |
| Pools de workers e buffers dimensionados para a carga medida | Remover o ciclo de render ou o ciclo de retry |
| Um covering index acrescentado online | Expirar os dados da aplicação que crescem sem limite |
| Retries e timeouts do HAProxy afinados, um contexto SELinux corrigido | Reduzir o payload e os scripts enviados ao browser |
Não alteramos o seu código. Nomeamos a linha, mostramos a medição que aponta para ela e mantemos o website no ar enquanto a corrige.
Respostas diretas
Como sei se é o meu servidor ou a minha aplicação que está lenta?+
Leia a margem durante o período lento: CPU idle e steal, memória disponível, await do disco. Se os três têm espaço, a restrição está acima do hardware, na aplicação ou num serviço que ela chama. O tempo até ao primeiro byte em localhost comparado com o edge confirma qual a camada.
Como encontram uma query de base de dados lenta?+
Ordenamos por digest, não por plan handle, para que uma query lógica com muitas parametrizações mostre o seu custo total numa linha. Depois verificamos contagens de linhas e índices existentes antes de escrever qualquer DDL.
Conseguem distinguir um bot de um pico real de tráfego?+
A partir do access log, pela frequência dos URL. Uma mão-cheia de URL repetidos milhares de vezes é o website a chamar-se a si próprio, a ordem do sitemap é um crawler, uma subida ampla é procura. Cada um tem uma solução diferente.
Alteram o meu código?+
Não. O que estiver do lado da infraestrutura corrigimos no edge no próprio dia, de forma reversível. O que estiver no seu código devolvemos como a alteração exata, com a medição que a justifica.
O seu website está lento e ninguém concorda porquê.
Fale com um engenheiro que mede cada salto antes de tocar no que quer que seja.
Fale com um engenheiroChegou ao fim.
Ponha a leitura em prática
O que executa?
Fale-nos da carga de trabalho, do tráfego e dos requisitos de recuperação. Comece pelo configurador de servidores ou discuta os detalhes com um engenheiro.
Escrito pelos engenheiros que constroem e operam a infraestrutura que descreve.Fale com um engenheiro
