Apache alcançando MaxClients e bloqueando o servidor

9

Atualmente, tenho um servidor Apache2 em execução com mpm-prefork e mod_php em um VPS OpenVZ com RAM de 512M real / 1024M burstable (sem troca). Depois de executar alguns testes, descobri que o tamanho máximo do processo que o Apache obtém é 23M, então eu defini MaxClients para 25 (23M x 25 = 575 MB, ok para mim). Eu decidi executar alguns testes de carga no meu servidor, e os resultados me deixaram confuso.

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

Quando executo ab com 24 conexões simultâneas, tudo parece bem. Claro, a CPU aumenta, a RAM livre diminui e o resultado é de cerca de 2 a 3 vezes o tempo de resposta por solicitação.

Mas se eu executar ab com 25 conexões simultâneas (meu limite de servidor), o Apache apenas trava depois de alguns segundos. Ele começa a processar as solicitações, depois pára de responder, a CPU volta a 100% inativa e ab expira. O log do Apache diz que ele atingiu MaxClients .

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

Minha pergunta: esse comportamento esperado? Por que o Apache simplesmente morre quando alcança MaxClients ? Se funciona com 24 conexões, não deveria funcionar com 25, levando mais tempo para responder a cada solicitação e fazer o resto do resto?

Parece meio estranho para mim que qualquer criança rodando ab possa matar um servidor apenas configurando as conexões simultâneas para os servidores MaxClients .

    
por Rodrigo Sieiro 18.04.2010 / 19:06

2 respostas

17

HA! Eu finalmente encontrei o problema sozinho. É mais relacionado à programação do que admin do servidor, mas eu decidi colocar a resposta aqui de qualquer maneira porque pesquisando o google eu descobri que não sou o único com esse tipo de problema (e como 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 a adição de uma imagem ao cabeçalho do blog. Para permitir isso, verifica o tamanho da imagem usando a função getimagesize() do PHP. Como essa função estava abrindo outra conexão http com o servidor para obter a imagem, cada solicitação de ab estava criando outra solicitação internamente a partir do PHP. Como eu estava usando todos os meus slots disponíveis no servidor, essas solicitações PHP foram colocadas na fila, mas o Apache nunca poderia acessá-las, porque todos os processos foram bloqueados com a solicitação original esperando por um slot para concluir a solicitação interna do PHP. >

Basicamente, o PHP estava colocando meu servidor em um estado de deadlock, e o Apache só começaria a funcionar normalmente depois que essas conexões atingissem o tempo limite de espera por sua solicitação "filho".

Depois que eu removi essa função do meu tema, agora posso ab meu servidor com quantas conexões simultâneas eu quiser, e o Apache está enfileirando-as conforme o esperado.

    
por 18.04.2010 / 22:49
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 de soquetes, dependendo do tamanho do seu backlog.

O segundo problema é que, independentemente do que você esteja executando, que leva de 2 a 3 segundos, está demorando para responder que as 25 conexões simultâneas estão diminuindo a velocidade. sleep (1) pode funcionar, mas, algo em que você está fazendo o bloqueio de arquivos ou o bloqueio de tabelas do mysql, cada solicitação paralela pode estar aguardando o anterior para ser concluída até atingir o tempo limite de 45 segundos.

23mb soa pequeno para um processo apache com mod_php e qualquer módulo carregado, então, eu suspeito que você esteja vendo esses processos do apache pegando um pouco mais de memória RAM enquanto seu aplicativo está rodando. Você não pode fazer contas com MaxClients e memória assim ... será um pouco próximo, mas nunca se 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 56M e 49M.

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

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

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

    
por 18.04.2010 / 22:10