Como investigar um vazamento de memória com o Apache e o PHP?

15

Estamos executando um site pesado do Drupal que realiza modelagem financeira. Parece que estamos correndo para algum tipo de vazamento de memória, dado o fato de que a memória usada pelo apache aumenta enquanto o número de processos do apache permanece estável:

Sabemos que o problema de memória está vindo do apache / PHP porque sempre que emitimos um /etc/init.d/httpd reload , o uso da memória cai (veja a imagem acima e abaixo das saídas da CLI):

Antes de atualizar o httpd

$ free
             total       used       free     shared    buffers     cached
Mem:      49447692   45926468    3521224          0     191100   22609728
-/+ buffers/cache:   23125640   26322052
Swap:      2097144     536552    1560592

Após o carregamento do httpd

$ free
             total       used       free     shared    buffers     cached
Mem:      49447692   28905752   20541940          0     191360   22598428
-/+ buffers/cache:    6115964   43331728
Swap:      2097144     536552    1560592

Cada thread do apache recebe um PHP memory_limit de 512MB, o que explica o alto uso de memória, o baixo volume de solicitações e max_execution_time de 120 segundos que devem terminar threads cuja execução está demorando mais e, portanto, devem evitar o constante crescimento no uso de memória que estamos vendo.

P: Como poderíamos investigar o que está causando esse vazamento de memória?

Idealmente, estou procurando as etapas de solução de problemas que posso executar no sistema sem precisar incomodar a equipe de desenvolvimento.

Informação adicional:

OS: RHEL 5.6
PHP: 5.3
Drupal: 6.x
MySQL: 5.6

FYI estamos cientes do problema de troca que estamos investigando separadamente e não tem nada a ver com o vazamento de memória que observamos antes da troca começar a ocorrer.

    
por Max 13.03.2012 / 09:13

4 respostas

11

We know the memory problem is coming from apache/PHP because whenever we issue a /etc/init.d/httpd reload the memory usage drops

Não - isso significa que está relacionado ao tráfego da web. Você passou a mencionar que você está executando o mysql na caixa - presumivelmente gerenciando dados para o servidor da Web - poderia facilmente ser o culpado aqui. Assim como outros serviços que sua webstack usa que você não mencionou.

Each apache thread is assigned a PHP memory_limit of 512MB which explains

Não, não. Você está reportando uma média de 7 e um máximo de 25 servidores ocupados - mas seu gráfico de memória mostra um delta de cerca de 25Gb.

Realmente você deve começar de novo com o ajuste HTTP básico - você parece estar rodando uma constante de 256 httpds, mas seu pico de uso é de 25 - isso é simplesmente estúpido.

and a max_execution_time of 120 sec which should terminate threads which execution is taking longer

Não - somente se o segmento de execução estiver dentro do interpretador PHP - não se o PHP estiver bloqueado.

that performs financial modeling

(suspiro)

Teria sido útil se você tivesse fornecido detalhes de como você configurou o Apache, threaded ou prefork, qual versão, como o PHP é invocado (module, cgi, fastcgi), se você está usando conexões persistentes, se você usa procedimentos armazenados.

Eu sugiro que você comece movendo o mysql para uma máquina separada e pare de usar conexões persistentes (se você estiver usando-as atualmente). Defina o limite de memória muito mais baixo e substitua-o por script. Certifique-se de que você tenha o coletor de lixo de referência circular instalado e configurado.

    
por 13.03.2012 / 10:55
2

Você provavelmente resolveu seu problema agora. Como provisório para impedir que o servidor troque / debulha, eu executo o seguinte comando a cada hora a partir do cron:

#!/bin/sh 
sync; echo 3 > /proc/sys/vm/drop_caches

Eu não estou dizendo que isso é uma solução, apenas uma maneira de manter as coisas funcionando e minimizar a redução de custos à medida que você investiga a causa real do vazamento de memória.

Mais detalhes podem ser encontrados aqui.

link

    
por 11.03.2013 / 21:44
1

Aparentemente, esta é a maneira como o PHP funciona - e se você está fazendo longos loops onde você está alocando objetos e quem sabe se você os está passando também por referência, então o único jeito de lidar com isso é após N pedidos de cada processo PHP para pará-lo. Se você executar o PHP como CGI, cada solicitação fará com que ele reapareça - assim, nenhum vazamento de memória e a queda de desempenho podem não ser tão grandes. Você também pode executar o fast-cgi, onde, por exemplo, cada 1000 pedidos o processo php-fcgi é morto e sua memória é liberada - novamente sem vazamento de memória. Se você executar o PHP como módulo mod_php, você pode tentar configurar maxrequests no httpd.conf para ver se isso ajuda. Eu tentaria configurar, e. 10 - se for funcionar, a queda de desempenho não será alta, mas não deve haver vazamentos de memória, mesmo sob pico intenso quando todos os 250 httpds estiverem em uso (10 * 250 = 2500 - para cada 10MB de uso de memória é de 25GB - então talvez, se você não tiver 128GB de RAM, tente também diminuir o número de processos httpd para, por exemplo, 50).

    
por 13.03.2012 / 12:59
-1

Verifique a memória no arquivo global php.ini. Não simplesmente decalre valure como 1 G etc ... Eu recomendo que um php.ini local é trazido para essa conta para não impactar o servidor inteiro. Eu recomendaria definir o limite global php.ini para cerca de 64M, pois isso é normalmente suficiente para a maioria das contas

verifique também as configurações do seu apache

    
por 04.06.2015 / 10:33