Apache morreu; O suspeito é ulimit mas não pode reproduzir

1

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:

  1. Existe uma maneira melhor de configurar o módulo prefork? Acabamos de migrar de um servidor mais antigo para esse servidor mais novo. O mais antigo tinha o ServerLimit e MaxClients definido para 512. Eu imaginei que poderia também definir 2000 para evitar ter que mudá-lo novamente no futuro previsível.
  2. Eu tentei ajustar o ulimit nproc para um número LOW para tentar reproduzir o erro. No limits.conf eu configurei * hard nproc 15 , mas o Apache ainda gerava cerca de 30 filhos quando eu executava ab . Estou faltando alguma coisa?
  3. Apesar do número 2, a solução aqui é elevar a configuração nproc para algo maior como 10000?
  4. Eu também gostaria de implementar algo que impeça os usuários de fazer tantas tentativas. No passado, usei 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

    
por Safado 12.12.2012 / 18:37

0 respostas