O que poderia causar o bloqueio de um servidor apache nos processos de “envio de resposta”?

4

Estou executando um servidor CentOS como uma pilha LAMP que atende a um aplicativo php personalizado. Em intervalos aparentemente aleatórios, diminui a velocidade. Olhando para a página de status do servidor, vejo a lista de PIDs bloqueada com os vários da mesma chamada de ajax, todos solicitados do IP do cliente de um usuário. (O IP muda, mas é sempre apenas um)

Eu vejo que o status dos parâmetros 'M' é W para "Sending Reply" , o que isso poderia significar?

A lentidão geralmente é resolvida após 5 minutos a uma hora. No entanto, outro dia eu decidi realizar um:

service httpd restart graceful.

Isso resolveu totalmente o problema - por 10 minutos. Abaixo está o status do servidor 14 minutos depois, lento e trancado. Parece que as solicitações rapidamente aumentam para 50 e o servidor fica mais lento.

Pontos a considerar:

  • Várias solicitações sempre do mesmo IP
  • Solicitações duram um tempo máximo (SS) de ~ 200 segundos
  • Todas as solicitações indo para um script ajax.php
  • Lentidão às vezes não acontece por algumas semanas, depois várias em alguns dias
  • Os usuários só têm algumas guias abertas no navegador do endereço do servidor ~ total de 25
  • Aparentemente, os piores problemas ocorrem no final da tarde

Então,minhaperguntaé:Oquepoderiaestarcausandoessebloqueio,eporquetodasassolicitaçõessão"Sending Reply" ?

Aqui está o httpd.conf

<IfModule worker.c>
StartServers         2
MaxClients          50
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>
    
por blarg 31.03.2014 / 11:28

2 respostas

2

Parece que essas conexões ficam presas por um longo tempo (SS é o tempo que a solicitação foi recebida, e algumas delas estão ocorrendo vários minutos).

Meu instinto me diz para olhar o banco de dados e o aplicativo PHP. Verifique se você tem conexões disponíveis suficientes no pool, verifique se há tarefas de manutenção (o vácuo completo pode bloquear o banco de dados por um longo período de tempo!) E registre consultas longas para ver se você está fazendo algo que pode bloquear uma tabela importante. Também pode ser um problema no script PHP que impede sua finalização em tempo hábil.

Aqui é uma página com algumas dicas úteis de depuração para esse tipo de situações.

    
por 31.03.2014 / 11:58
0

Dado que no seu caso as conexões são da sua LAN, é improvável que seja um ataque, mas no meu caso eu tinha 1 IP externo (de cada vez) fazendo as mesmas coisas em um site wordpress (mais recente) e , mesmo em coisas como:

/wp-content/plugins/wpmarketplace/readme.txt

que não existe no meu servidor (a maioria dos recursos GET não existia e havia muitos arquivos txt e css sendo GETed). Houve também pedidos POST em vários arquivos php, levando à mesma lentidão e, eventualmente, congelar.

Então, meu palpite é que este é um script muito mal escrito para verificar sites vulneráveis, resultando em um DoS. Ou pode ser realmente um DoS e não um script de buggy, no entanto tem sido há séculos desde que eu vi um, hoje em dia as pessoas fazem DDoSes.

Atualmente, estou trabalhando em alguns scripts para controlar isso. Depois de tê-los, vou postar de volta, talvez ajude alguém.

Edição de laster:

depois de muitos testes, acho que finalmente consegui controlar as coisas. Vamos supor que você crie um novo script /root/check_httpd.sh (explicações na parte inferior)

cnt='ps -Af | grep httpd | grep -v rotatelogs | grep -v grep | wc -l'
now='date +%Y-%m-%d_%H-%M'

# change the 40 below to something meaningful to your server
if [ $cnt -ge 40 ]
then
  /usr/bin/wget -q -O /root/apache_status_$now http://<your server here>/server-status
  /sbin/service httpd restart
fi

# change hda to your partition/disk which is being "killed" by httpd during the freeze
dsk='/usr/bin/iostat -dx /dev/hda 5 2 | grep hda | tail -1 | awk '{print $12}''

if (( $(echo "$dsk > 98" |bc -l) ))
then
  /bin/sleep 5
  dsk='/usr/bin/iostat -dx /dev/hda 5 2 | grep hda | tail -1 | awk '{print $12}''
  if (( $(echo "$dsk > 98" |bc -l) ))
  then
    /sbin/service httpd restart
  fi
fi

Você adiciona isso ao cron como:

0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /root/check_httpd.sh

não se esqueça de

chmod +x /root/check_httpd.sh

E as explicações.

Portanto, no meu caso, inicialmente, notei que (durante o congelamento) a página de status do httpd mostrava vários filhos httpd do estado "W", com vários tempos de espera em vários recursos, alguns válidos, outros inválidos. Passei muito tempo com várias opções para obter um cenário de 90% com base na página de status para descobrir quando o servidor está congelado e não sob uso pesado. Sem sorte. Mas então eu percebi que, normalmente, mesmo sob carga "pesada", minha contagem de processos filho httpd ainda estaria abaixo de 20-30 (meu site é "lite"), então fiz alguns testes e descobri que uma contagem de 40 httpd filho count sempre acontece durante o congelamento (OBSERVAÇÃO: você pode remover o status wget daquela seção, ele está lá para você confirmar que durante a reinicialização para qualquer valor que você escolher, existe um congelamento. Você verifica manualmente)

No entanto, isso sozinho não iria cortá-lo. Eu ainda tinha casos em que o servidor congelou por mais de 24 horas antes que 40 contassem. Procurando mais um pouco eu encontrei o utilitário topo que eu deixei rodando em um terminal de massa, então sempre que o servidor congelava eu podia ver quais recursos exatos estavam sendo usados. consumido muito. E notei que era o HDD. Então, veio a segunda verificação para o uso do HDD, mas como você sabe, o uso do hdd dispara de vez em quando, então 1 verificação sozinha resulta em falsos positivos. O que eu fiz foi fazer outra verificação após alguns segundos e só então reiniciar o httpd, se necessário.

Você precisará jogar um pouco no seu servidor e ajustar os valores de limite para torná-los adequados ao seu ambiente e padrões de uso.

    
por 07.06.2016 / 22:58