Apache morreu na noite passada. O log de erros mostra isso
[alert] (11)Resource temporarily unavailable: setuid: unable to change to uid: 48
Navegando pela Internet, todo mundo parece dizer que isso é um problema com o ulimit no Linux. Se bem entendi, ulimit tem um padrão para limitar o número de processos simultâneos a qualquer usuário não-root para 1024. Se esse número máximo para um usuário (apache, neste caso) for atingido, ele não poderá criar mais processos. Assim explicando porque não pode setuid ao usuário do apache quando tentou gerar um novo filho.
Ontem à noite, pedimos a um usuário do nosso aplicativo da Web que fizesse 1100+ solicitações GET para a mesma página no espaço de cerca de 1 minuto e foi quando o servidor morreu.
Meu arquivo de configuração do Apache tem isto:
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 2000
MaxClients 2000
MaxRequestsPerChild 4000
</IfModule>
KeepAlive On
MaxKeepAliveTimeout 5
KeepAliveTimeout 5
Se o meu MaxClients for 2000 e o MaxSpareServers for 20, isso significa que, para o Apache ter atingido o ulimit para processos, ele precisaria ter mais de 1000 processos ocupado , o que eu simplesmente Não vejo isso acontecendo, considerando que essas solicitações GET eram pequenas e poderiam facilmente lidar com 20 a 30 solicitações por segundo. Além disso, MaxRequestsPerChild está configurado para 4000, então não deveria estar gerando tantos novos filhos, certo? Então, foi ulimit realmente o culpado aqui por que não poderia ser definido?
Eu usei a ferramenta ab
do Apache para tentar reproduzir isso em uma compilação local muito menos poderosa e não posso. Mesmo o hardware menos potente pode lidar com milhares de conexões em um minuto com o desempenho ok . Ele fica mais lento se eu tento acessar o servidor pela Web ao mesmo tempo, mas o Apache não sai do ar.
Então, aqui estão minhas perguntas:
* hard nproc 15
, mas o Apache ainda gerava cerca de 30 filhos quando eu executava ab
. Estou faltando alguma coisa? iptables
para bloquear usuários que fizeram mais de 5 solicitações SSH em um minuto. Pensei em fazer algo semelhante para solicitações http, mas queria saber se há soluções melhores por aí. Eu já ouvi falar de fail2ban e mod_security e tal, mas não tenho certeza do que eles fazem. Eles me beneficiariam nesse caso? Alguma outra sugestão? Informações do servidor: RHEL 6.3, Apache 2.2.15
Tags iptables ulimit apache-2.2 rhel6