Cerca de uma vez por semana, mas às vezes até duas vezes por dia após uma boa execução por dias, minhas instâncias do EC2 ficam sem resposta. Os gráficos de memória de Munin contam uma história bastante direta: a memória alocada para "aplicativos" começa a crescer e não para até que a troca seja totalmente usada e a instância seja efetivamente derrubada. Outro gráfico personalizado mostra que o processo em constante crescimento é o apache2.
Eu executo uma configuração padrão do Apache pré-fork com mod_php e alguns scripts PHP. Como você pode ver no gráfico abaixo, algo acontece que aciona os processos do apache2 para começar a consumir mais e mais memória. O primeiro pico verde que peguei a tempo e reiniciei o Apache antes que as coisas saíssem do controle. O segundo pico foi um pouco mais longe e a instância teve que ser reiniciada imediatamente.
O que eu quero saber é como melhor depurar isso. Além de configurar o PHP com FastCGI e executá-lo em seus próprios processos, qual é uma boa maneira de descobrir se é o Apache ou uma combinação de PHP e meu código que está causando o uso excessivo de memória? Que medidas vocês tomariam para rastrear esse problema?
ATUALIZAÇÃO: Consegui rastrear o vazamento depois de me envolver, como sugeriu Matt abaixo.
Depois de encontrar um processo apache2 que crescia gradualmente e continuamente na memória, adicionei mais algumas chamadas error_log () ao meu script PHP que imprimia a quantidade total de RSS usado em vários pontos de sua execução (usando a saída de ps). No entanto, isso acabou sendo enganoso - embora parecesse que o RSS pulou apenas após a execução do meu script, a depuração posterior revelou que esse não era realmente o caso. Seja cuidadoso!
Felizmente, todas essas chamadas error_log () acabaram sendo úteis no final. Quando iniciei strace ( strace -p <pid> -tt -o trace.log -s 256
), vi que para cada solicitação, o processo estava alocando cerca de 400k de memória (procure a chamada do sistema 'brk' e subtraia o parâmetro da primeira chamada da última chamada - alguns geralmente vêm em um depois de outro). Em seguida, procurei a chamada mais recente do sistema 'write' que continha minha mensagem error_log (), que dizia em que ponto do script a memória estava sendo alocada. Com mais algumas chamadas error_log () estrategicamente colocadas para identificar o local com mais precisão, finalmente encontrei o culpado.
A memória estava vazando quando chamamos curl_exec () do nosso script PHP. Algum código de ondulação relacionado ao manuseio de uma conexão SSL está fazendo algo errado - o vazamento desapareceu quando mudei para o HTTP. O changelog de Curl faz referência a alguns vazamentos de memória SSL que foram corrigidos na 7.19.5 (estávamos na 7.18.2), então tentarei isso a seguir.
Enquanto isso, estou executando um MaxRequestsPerChild muito baixo que mantém o Apache dentro de limites razoáveis. Obrigado a todos!