Apache alcançando o MaxClients e bloqueando o servidor

9

Atualmente, tenho um servidor Apache2 em execução com mpm-preforke mod_phpem um OpenVZ VPS com 512M de RAM real / 1024M que pode ser estourada (sem troca). Depois de executar alguns testes, descobri que o tamanho máximo do processo que o Apache obtém é 23M, então configurei MaxClientspara 25 (23M x 25 = 575 MB, ok para mim). Decidi executar alguns testes de carga no meu servidor, e os resultados me deixaram perplexo.

Estou usando abna minha máquina desktop solicitando a página principal de um blog wordpress.

Quando corro abcom 24 conexões simultâneas, tudo parece bem. Claro, a CPU aumenta, a RAM livre diminui e o resultado é de cerca de 2-3s em tempo de resposta por solicitação.

Mas se eu rodar abcom 25 conexões simultâneas (limite do meu servidor), o Apache travará após alguns segundos. Ele inicia o processamento das solicitações e, em seguida, para de responder, a CPU volta para 100% ociosa e atinge o abtempo limite. O log do Apache diz que foi atingido MaxClients.

Quando isso acontece, o Apache se mantém bloqueado com 25 processos em execução (todos eles estão em "W" se eu verificar o status do servidor) e somente após a TimeOutconfiguração os processos começam a morrer e o servidor começa a responder novamente (no meu caso, está definido 45).

Minha pergunta: esse comportamento é esperado? Por que o Apache morre quando chega MaxClients? Se funciona com 24 conexões, não deve funcionar com 25, demorando talvez mais tempo para responder a cada solicitação e enfileirar o resto?

Parece-me meio estranho que qualquer criança correndo absozinha possa matar um servidor da Web apenas configurando as conexões simultâneas com os servidores MaxClients.

Rodrigo Sieiro
fonte

Respostas:

17

HA! Eu finalmente encontrei o problema sozinho. Está mais relacionado à programação do que ao administrador do servidor, mas decidi colocar a resposta aqui de qualquer maneira porque, ao pesquisar no google, descobri que não sou o único com esse tipo de problema (e desde que o Apache trava, o primeiro palpite é que há um problema com o servidor).

O problema não está no Apache, mas no meu Wordpress. Mais especificamente com o meu tema. Estou usando um tema chamado Lightworld e ele suporta adicionar uma imagem ao cabeçalho do blog. Para permitir isso, ele verifica o tamanho da imagem usando a função do PHP getimagesize(). Como essa função estava abrindo outra conexão http com o servidor para obter a imagem, cada solicitação de abestava criando outra solicitação internamente a partir do PHP. Como eu estava usando todos os slots disponíveis para o servidor, essas solicitações PHP foram colocadas na fila, mas o Apache nunca conseguiu acessá-las porque todos os seus processos foram bloqueados com a solicitação original aguardando um slot para concluir a solicitação interna do PHP.

Basicamente, o PHP estava colocando meu servidor em um estado de impasse, e o Apache só começava a funcionar normalmente depois que essas conexões atingiam o tempo limite, aguardando a solicitação "filha".

Depois que eu removi essa função do meu tema, agora posso usar abmeu servidor com quantas conexões simultâneas eu desejar e o Apache as enfileirará conforme o esperado.

Rodrigo Sieiro
fonte
Obrigado por postar isso aqui em cima, eu tenho tentado descobrir um problema com exatamente os mesmos sintomas há alguns dias - pense que também temos um impasse!
James Yale
como você determinou isso, estou interessado principalmente nos logs e ferramentas que você usou para determinar a solicitação de saída secundária.
Anirudh Goel
2

O que está acontecendo aqui é que você tem 25 threads capazes de aceitar conexões e está enviando 26 solicitações simultâneas. Essa última solicitação fica na fila do soquete, dependendo do tamanho da sua lista de pendências.

O segundo problema é que tudo o que você está executando, que leva de 2 a 3 segundos, está demorando o suficiente para responder que as 25 conexões simultâneas estão diminuindo a velocidade. sleep (1) pode funcionar, mas, algo em que você está travando arquivos ou travando tabelas do mysql, cada solicitação paralela pode estar aguardando a conclusão do processo antes de atingir o tempo limite de 45 segundos.

23mb parece pequeno para um processo apache com mod_php e quaisquer módulos carregados, então, suspeito que você possa estar vendo esses processos apache tendo um pouco mais de RAM à medida que seu aplicativo está sendo executado. Você não pode realmente fazer contas com o MaxClients e uma memória assim ... será um pouco próxima, mas você nunca sabe.

www-data  1495  0.1  0.9  56288 19996 ?        S    15:48   0:01 /usr/sbin/apache2 -k start
www-data  1500  0.0  0.5  49684 12436 ?        D    15:48   0:00 /usr/sbin/apache2 -k start

Há uma máquina, processos de 56 e 49 milhões.

outra máquina:

www-data  7767  0.1  0.1 213732 14840 ?        S    14:55   0:08 /usr/sbin/apache2 -k start
www-data  8020  0.2  0.1 212424 13660 ?        S    14:57   0:08 /usr/sbin/apache2 -k start

outra máquina:

www-data 28509  0.8  0.1 161720 10068 ?        S    14:39   0:43 /usr/sbin/apache2 -k start
www-data 28511  0.8  0.1 161932 10344 ?        S    14:39   0:43 /usr/sbin/apache2 -k start

Portanto, o uso da memória depende muito da tarefa, quais módulos são carregados etc. Nos últimos dois, acredito que desativamos o pdo & pdo_mysql, pois esse aplicativo não os utiliza.

A verdadeira questão é: o que você está fazendo e demorando 3 segundos? No mundo de hoje, isso é uma eternidade e é considerado um aplicativo 'bloqueador'. O Apache normalmente não morre, mas deixa esses encadeamentos na fila de pendências até que possa atendê-los ou o tempo limite das solicitações de espera. Acredito que seu aplicativo provavelmente esteja causando o tempo limite do apache. Experimente em uma página contendo apenas phpinfo (); e veja se os resultados são os mesmos.


fonte
Obrigado por todas as dicas! Estou ciente de que ainda preciso otimizar muitas coisas (comecei a configurar o servidor há alguns dias e é minha primeira experiência com um VPS), mas o problema era mais profundo do que isso ... Postei uma resposta no pergunta explicando qual era o problema no meu caso específico.
Rodrigo Sieiro