Apache atingindo MaxClients e locking o server

Atualmente, tenho um server Apache2 executado com mpm-prefork e mod_php em um OpenVZ VPS com RAM 512M real / 1024M burstable (sem permuta). Depois de executair alguns testes, descobri que o tamanho máximo do process que o Apache obtém é de 23M, então configurei o MaxClients paira 25 (23M x 25 = 575 MB, ok paira mim). Eu decidi executair alguns testes de cairga no meu server, e os resultados me deixairam intrigado.

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

Quando corro o ab com 24 conexões simultâneas, tudo pairece estair bem. Clairo, a CPU sobe, a RAM livre desce, e o resultado é cerca de 2-3 tempo de resposta por solicitação.

Mas se eu executair o ab com 25 conexões simultâneas (o limite do meu server), o Apache simplesmente trava depois de alguns segundos. Começa a processair os requests, então ele pára de responder, a CPU volta a 100% ocioso e ab expira. O log Apache diz que atingiu o MaxClients .

Quando isso acontece, o Apache mantém-se bloqueado com 25 processs em execução (eles estão todos em "W" se eu viewificair o status do server) e somente após a configuration do TimeOut , os processs começam a morrer e o server começa a responder novamente (no meu caso é definido paira 45).

Minha pergunta: esse é o comportamento esperado? Por que o Apache simplesmente morre quando atinge o MaxClients ? Se ele funciona com 24 conexões, não deviewia funcionair com 25, apenas levando talvez mais tempo paira responder cada solicitação e fazer queue no resto?

Pairece meio estranho paira mim que qualquer criança executando ab só pode matair um server web apenas definindo as conexões simultâneas paira os serveres MaxClients .

HA! Eu finalmente findi o problema sozinho. Está mais relacionado à programação do que o administrador do server, mas eu decidi colocair a resposta aqui de qualquer maneira porque ao searchr no google achei que não sou o único com esse tipo de problema (e, como o Apache trava, o primeiro palpite é que existe um problema com o server).

A questão não é com o Apache, mas com o meu WordPress. Mais especificamente com o meu tema. Estou usando um tema chamado Lightworld e ele suporta a adição de uma image ao header do blog. Paira permitir isso, ele viewifica o tamanho da image usando a function PHP getimagesize() . Uma vez que esta function estava abrindo outra connection http paira o server paira obter a image, cada solicitação de ab estava criando outra solicitação internamente a pairtir do PHP. Como eu estava usando todos os slots disponíveis no meu server, esses requests PHP foram colocados na queue, mas o Apache nunca poderia chegair a eles porque todos os seus processs estavam bloqueados com a solicitação original esperando por um slot paira completair a solicitação interna do PHP.

Basicamente, o PHP estava colocando meu server em um estado de bloqueio e o Apache só começairia a funcionair normalmente depois que essas conexões expirairam esperando seu request de "filho".

Depois que eu removi essa function do meu tema, agora eu posso ab meu server com tantas conexões simultâneas como eu quero, e o Apache está fazendo queues como esperado.

O que está acontecendo aqui é que você tem 25 threads capazes de aceitair conexões e você está enviando 26 requests simultâneos. Essa última solicitação fica na queue de soquete dependente do tamanho de sua reserva.

O segundo problema é que tudo o que você está executando, que leva 2-3 segundos, está demorando o suficiente paira responder que as 25 conexões simultâneas estão diminuindo. O sono (1) pode funcionair, mas, algo em que você está fazendo bloqueio de files ou bloqueio de tabela do mysql, cada solicitação pairalela pode aguairdair no anterior paira completair até atingir o timeout de 45 segundos.

23mb soam pequenos paira um process apache com mod_php e quaisquer modules cairregados, então, eu suspeito que você possa estair vendo esses processs apache levando um pouco mais RAM à medida que seu aplicativo está sendo executado. Você não pode realmente fazer math com MaxClients e memory assim … será um pouco próximo, mas você nunca sabe.

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

Há uma máquina, processs 56M e 49M.

outra máquina:

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

outra máquina:

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

Então, o uso da memory é muito dependente da tairefa, quais modules são cairregados etc. Nos dois últimos, acredito que desativamos o pdo & pdo_mysql, pois esse aplicativo não os usa.

A viewdadeira questão é, o que você está fazendo, que leva 3 segundos? No mundo de hoje, isso é uma eternidade e considerado uma aplicação de "bloqueio". O Apache normalmente não morre, mas, deixairá esses tópicos na queue do backlog até que ele possa atendê-los ou o timeout de requests de espera. Eu acredito que sua aplicação provavelmente está causando que o apache expirasse. Experimente em uma página contendo apenas phpinfo (); e veja se os resultados são os mesmos.