A tarefa cron do coletor de lixo do Ubuntu para sessões PHP leva 25 minutos para ser executada, por quê?

12

O Ubuntu tem uma configuração de tarefa cron que procura e exclui 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 para ser executado, com muito disco IO. Aqui está meu gráfico de uso da CPU:

Aexecuçãodelimpezaérepresentadapelospicosdecerceta.Noiníciodoperíodo,ostrabalhosdelimpezadoPHPeramagendadosnostempospadrãode09e39minutos.Às15:00,euremoviotempode39minutosdocron,entãoumtrabalhodelimpezacomodobrodotamanhoéexecutadocomametade(vocêpodeverospicosobtendoodobrodalarguraemetadedafrequência).

AquiestãoosgráficoscorrespondentesparaotempodeIO:

E operações de disco:

Nopicoemquehaviacercade14.000sessõesativas,alimpezapodeserexecutadapor25minutos,aparentementeusando100%deumnúcleodaCPUeoquepareceser100%dodiscoIOparaoPeríodointeiro.Porqueétãointensivoemrecursos?Umlsdodiretóriodesessão/var/lib/php5levaapenasumafraçãodesegundo.Então,porquedemora25minutosparaapararsessõesantigas?Existealgoqueeupossafazerparaacelerarisso?

Osistemadearquivosparaestedispositivoéatualmenteext4,rodandonoUbuntuPrecise12.0464-bit.

EDIT:Eususpeitoqueacargaédevidoaoprocessoincomum"fusor" (desde que eu espero um simples rm para ser uma visão maldita mais rápido do que o desempenho que estou vendo). Vou remover o uso do fusor e ver o que acontece.

    
por thenickdude 30.08.2012 / 04:51

5 respostas

8

A remoção de fuser deve ajudar. Esta tarefa executa um comando fuser (verifique se um arquivo está aberto no momento) para cada arquivo de sessão encontrado , que pode facilmente levar vários minutos em um sistema ocupado com sessões de 14k. Este era um bug do Debian (o Ubuntu é baseado no Debian).

Em vez de memcached, você também pode tentar usar o tmpfs (um sistema de arquivos na memória) para arquivos de sessão. Como o memcached, isso invalidaria as sessões na reinicialização (isso pode ser contornado fazendo backup desse diretório em algum lugar no script de desligamento e restaurando no script de inicialização), mas será muito mais fácil de configurar. Mas isso não ajudará no problema fuser .

    
por 30.08.2012 / 11:03
9

Parabéns por ter um site popular e conseguir mantê-lo em execução em uma máquina virtual por todo esse tempo.

Se você está realmente obtendo dois milhões de pageviews por dia, então você vai acumular MUITAS sessões de PHP no sistema de arquivos, e eles levarão muito tempo para serem excluídos, não importa se você usa fuser ou rm ou um aspirador de pó.

Nesse ponto, recomendo que você procure maneiras alternativas de armazenar suas sessões:

  • Uma opção é armazenar sessões em memcached . Isso é muito rápido, mas se o servidor travar ou reiniciar, todas as suas sessões serão perdidas e todos serão desconectados.
  • Você também pode armazenar sessões em um banco de dados. Isso seria um pouco mais lento que o memcached, mas o banco de dados seria persistente e você poderia limpar as sessões antigas com uma simples consulta SQL. Para implementar isso, porém, você precisa escrever um manipulador de sessão personalizado .
por 30.08.2012 / 05:12
4

Assim, as opções de armazenamento de sessão do Memcached e do banco de dados sugeridas pelos usuários aqui são boas escolhas para aumentar o desempenho, cada uma com seus próprios benefícios e desvantagens.

Mas por testes de desempenho, descobri que o enorme custo de desempenho da manutenção desta sessão é quase totalmente baixo para a chamada para fuser no trabalho cron. Aqui estão os gráficos de desempenho depois de reverter para a tarefa cron do Natty / Oneiric que usa rm em vez de fuser para aparar sessões antigas, a alternância acontece à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 de operações de disco são agora muito menores em magnitude e aproximadamente tão finos quanto esse gráfico pode medir, mostrando uma pequena e curta interrupção em que o desempenho anterior do servidor foi significativamente reduzido por 25 minutos. O uso extra de CPU é totalmente eliminado, agora é um trabalho vinculado a E / S.

(uma tarefa de E / S não relacionada é executada às 05:00 e a tarefa da CPU é executada às 7:40, o que causa seus próprios picos nesses gráficos)

A tarefa cron modificada que estou executando agora é:

09 *     * * *     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) -print0 \
   | xargs -n 200 -r -0 rm
    
por 30.08.2012 / 12:19
0

Com esse tipo de tráfego, você não deve colocar sessões em um dis. Você deveria estar usando algo como memcache. Tudo o que você precisa fazer é configurar o php e não haverá necessidade de alteração de código. Veja por exemplo

link

O motivo pelo 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, dado o tamanho da sessão que você definiu no seu código.

    
por 30.08.2012 / 05:11
0

Me deparei com este post ao fazer algumas pesquisas sobre as sessões. Embora a resposta aceita seja muito boa (e a chamada do fusor foi removida do script do 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 o ext4. Os diretórios no ext4 armazenam dados de arquivo 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 em 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á recursando nesses diretórios - a tarefa cron acima não funciona).

Grande parte do custo da operação (depois de remover a chamada para o fusor) surge de olhar para arquivos que ainda não estão obsoletos. Usando (por exemplo) um único nível de subdiretórios, e 16 cron jobs procurando em cada subdiretório (0 /, 1 /, ... d /, e /, f /) irão suavizar os problemas de carga que surgem.

Usar um manipulador de sessão personalizado com um substrato mais rápido ajudará - mas há muito por onde escolher (memcache, redis, soquete de manipulador mysql ...) deixando de lado o intervalo de qualidade dos publicados na Internet, que você escolhe depende nos requisitos exatos com relação à sua aplicação, infraestrutura e habilidades, para não esquecer que freqüentemente existem diferenças no manuseio da semântica (notavelmente bloqueio) comparado com o manipulador padrão.

    
por 03.05.2018 / 00:29