O Ubuntu possui um trabalho cron configurado para procurar e excluir sessões antigas do PHP:
# Look for and purge old sessions every 30 minutes
09,39 * * * * root [ -x /usr/lib/php5/maxlifetime ] \
&& [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
-maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
fuser -s {} 2> /dev/null \; -delete
Meu problema é que esse processo está demorando muito tempo para ser executado, com muitas E / S de disco. Aqui está o meu gráfico de uso da CPU:
A execução da limpeza é representada pelos pontos da cerceta. No início do período, os trabalhos de limpeza do PHP eram agendados nos horários padrão de 09 e 39 minutos. Às 15:00, removi o tempo de 39 minutos do cron, portanto, um trabalho de limpeza com o dobro do tamanho é executado com metade da frequência (você pode ver os picos obterem o dobro da largura e a metade da frequência).
Aqui estão os gráficos correspondentes para o tempo de IO:
E operações de disco:
No pico em que havia cerca de 14.000 sessões ativas, a limpeza pode ser executada por 25 minutos, aparentemente usando 100% de um núcleo da CPU e o que parece ser 100% da E / S do disco durante todo o período. Por que é tão intensivo em recursos? Um ls
diretório da sessão /var/lib/php5
leva apenas uma fração de segundo. Então, por que são necessários 25 minutos para aparar as sessões antigas? Há algo que eu possa fazer para acelerar isso?
O sistema de arquivos deste dispositivo está atualmente ext4, sendo executado no Ubuntu Precise 12.04 de 64 bits.
Edição: Eu suspeito que a carga é devido ao processo incomum "fusor" (desde que eu espero que um simples rm
seja uma visão muito mais rápida do que o desempenho que estou vendo). Vou remover o uso do fusor e ver o que acontece.
fonte
Respostas:
A remoção de
fuser
deve ajudar. Este trabalho executa umfuser
comando (verifique se um arquivo está aberto no momento) para cada arquivo de sessão encontrado , o que pode facilmente levar alguns minutos em um sistema ocupado com 14k sessões. Este foi um bug do Debian (o Ubuntu é baseado no Debian).Em vez de memcached, você também pode tentar usar tmpfs (um sistema de arquivos na memória) para arquivos de sessão. Assim como o memcached, isso invalidaria as sessões na reinicialização (isso pode ser contornado, fazendo backup deste diretório em algum lugar do script de desligamento e restaurando o script de inicialização), mas será muito mais fácil de configurar. Mas isso não vai ajudar com o
fuser
problema.fonte
fuser
processos em um estado zumbi consumindo memória, o que leva a uma falha no servidor. Eu acho que isso já foi corrigido na versão do psmisc que estou usando.fuser
processos, todos os quais devem procurar/proc/
arquivos abertos no todo .Parabéns por ter um site popular e por mantê-lo funcionando em uma máquina virtual por todo esse tempo.
Se você está realmente puxando em dois milhões de pageviews por dia, então você está indo para empilhar um monte de sessões PHP no sistema de arquivos, e eles vão levar um longo tempo para apagar não importa se você usa
fuser
ourm
ou um aspirador de pó.Nesse ponto, recomendo que você procure maneiras alternativas de armazenar suas sessões:
memcached
. Isso é muito rápido, mas se o servidor travar ou reiniciar, todas as suas sessões serão perdidas e todos sairão.fonte
rm
.Portanto, as opções de armazenamento do Memcached e da sessão de banco de dados sugeridas pelos usuários aqui são boas opções para aumentar o desempenho, cada uma com seus próprios benefícios e desvantagens.
Mas, testando o desempenho, descobri que o enorme custo de desempenho dessa manutenção de sessão se deve quase inteiramente à chamada
fuser
no trabalho cron. Aqui estão os gráficos de desempenho após a reversão para o trabalho cron Natty / Oneiric, que usa emrm
vez defuser
aparar sessões antigas, a alternância ocorre às 2:30.Você pode ver que a degradação periódica do desempenho causada pela limpeza da sessão PHP do Ubuntu é quase totalmente removida. Os picos mostrados no gráfico Operações de disco agora são muito menores em magnitude e tão finos quanto esse gráfico pode medir, mostrando uma pequena e curta interrupção em que anteriormente o desempenho do servidor era significativamente reduzido por 25 minutos. O uso extra da CPU é totalmente eliminado, agora este é um trabalho vinculado a E / S.
(um trabalho de E / S não relacionado é executado às 05:00 e o trabalho de CPU é executado às 7:40, o que causa seus próprios picos nesses gráficos)
O trabalho cron modificado que estou executando agora é:
fonte
-print0 | xargs ...
não é necessário - você pode simplesmente sair de-delete
lá. Mas funcionará nos dois sentidos com velocidade comparável.Me deparei com este post ao fazer uma pesquisa sobre sessões. Embora a resposta aceita seja muito boa (e a chamada do fusor tenha sido removida do script gc por algum tempo), acho que vale a pena observar algumas outras considerações, caso alguém se depare com um problema semelhante.
No cenário descrito, o OP estava usando ext4. Os diretórios no ext4 armazenam dados de arquivos em um formato de banco de dados htree - o que significa que há um impacto insignificante na retenção de muitos arquivos em um único diretório, em comparação com a distribuição deles em vários diretórios. Isso não é verdade para todos os sistemas de arquivos. O manipulador padrão no PHP permite que você use vários subdiretórios para arquivos de sessão (mas observe que você deve verificar se o processo de controle está recorrendo nesses diretórios - o trabalho cron acima não).
Muito do custo da operação (após a remoção da chamada para o fusor) decorre da observação de arquivos que ainda não estão obsoletos. O uso (por exemplo) de um único nível de subdiretórios e 16 tarefas cron procurando em cada subdiretório (0 /, 1 /, ... d /, e /, f /) suavizará os choques de carga resultantes.
Usar um manipulador de sessão personalizado com um substrato mais rápido ajudará - mas há muito por onde escolher (memcache, redis, soquete do manipulador mysql ...) deixando de lado o intervalo de qualidade daqueles publicados na Internet, que você escolhe depende da exata requisitos em relação à sua aplicação, infraestrutura e habilidades, para não esquecer que frequentemente existem diferenças no tratamento da semântica (principalmente o bloqueio) em comparação com o manipulador padrão.
fonte
Com esse tipo de tráfego, você não deve colocar sessões em um dis. Você deve usar algo como memcache. Tudo que você precisa fazer é configurar o php e não haverá necessidade de alterar o código. Veja por exemplo
http://www.dotdeb.org/2008/08/25/storing-your-php-sessions-using-memcached/
A razão pela qual está demorando tanto é devido à enorme quantidade de arquivos que ele precisa classificar para ver quais podem ser excluídos. O Memcache pode expirar automaticamente, considerando a duração da sessão que você definiu no seu código.
fonte