Problemas do Apache no teste de desempenho com mod_reqtimeout

2

Temos 2 servidores Apache atrás de um balanceador de carga que estão conectados a 2 servidores de aplicativos (JBoss) via mod ajp.

Para esses servidores da Web, os dispositivos móveis se conectam por meio de uma API REST.

Em nosso teste de desempenho, encontramos rapidamente um monte de NonHttpResponse: erros que identificamos como sendo provenientes de mod_reqtimeout:

[Mon Mar 16 14:42:49.324705 2015] [reqtimeout:info] [pid 27914:tid 140628428449536] [client 1.2.3.4:48280] AH01382: Request header read timeout

... que é configurado da seguinte forma:

<IfModule reqtimeout_module>
    RequestReadTimeout header=10-20,minrate=500
    RequestReadTimeout body=10,minrate=500
</IfModule>

Consegui me livrar desses erros aumentando esses valores para

RequestReadTimeout header=20-60,minrate=100

Mas esta não pode ser a solução, já que com alguns usuários simultâneos o problema ocorreu novamente (há um requisito para poder atender 300 usuários simultâneos - 100 funcionaram muito bem, com 300 nós tivemos mais de 10.000 desses pedidos) cabeçalho ler erros de tempo limite). Eu suspeito que seja a interação dos apaches KeepAlive, nossa configuração mod_ajp e mod_reqtimeout que leva o mod_reqtimeout à conclusão de que há um ataque lento em andamento (para muitas conexões abertas que não fazem nada) e peço gentilmente sua ajuda para ajustar esses parâmetros.

Um problema adicional é um firewall entre o servidor da web e o servidor de aplicativos, que eu suspeito que tenha matado as conexões inativas abertas. Eu li sobre a desativação do KeepAlive completamente para resolver isso, mas como eu disse, todos os nossos clientes são dispositivos móveis, então isso provavelmente não é uma opção (?).

Aqui estão as outras configurações (partes de):

workers.properties:

worker.list=server
worker.maintain=60

worker.server.type=ajp13
worker.server.host=server
worker.server.port=15869
worker.server.socket_keepalive=True
worker.server.connection_pool_timeout=600
worker.server.ping_mode=A
worker.server.connection_ping_interval=60

mod_prefork:

<IfModule prefork.c>
    StartServers         5
    MinSpareServers      5
    MaxSpareServers     10
    #MaxClients         256
    MaxClients         300
    MaxRequestsPerChild  0
</IfModule>

mainserver.conf:

Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

ssl.conf (dispositivos móveis conectados via ssl):

Timeout 1200
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 10
    
por Michael Niemand 25.03.2015 / 10:55

1 resposta

1

É incomum que você esteja usando o MPM "prefork" no que parece ser essencialmente um proxy reverso, o MPM híbrido "trabalhador" tem melhor escalabilidade, mas esse não é o problema.

A mitigação de DoS geralmente é melhor tratada (se não pelo seu provedor de serviços de Internet) no dispositivo front-end que finaliza as solicitações do cliente, a partir de sua descrição é um balanceador de carga, não o Apache. Qualquer balanceador de carga competente será ciente do HTTP (ou seja, "Camada 7"), isso provavelmente resultará no buffer de solicitações HTTP. Isso também se aplica se o balanceador de carga estiver encerrando o HTTPS, mas menos se o balanceador de carga estiver simplesmente retransmitindo as conexões HTTPS (pois não pode ver as solicitações HTTP para armazená-las em buffer). Também não se aplica se o seu balanceador de carga for um simples balanceador de carga do tipo "Camada 3/4" NAT.

Quanto à possível causa dos tempos limite:

  • sua instância SSL KeepAliveTimeout é igual ao tempo limite de leitura do cabeçalho RequestReadTimeout , é possível que haja uma corrida em que o tempo limite do keepalive seja atingido no meio da solicitação / cabeçalhos de entrada do cliente. Se eu tentar reproduzir isso, além de erros AH01382 também recebo AH01991 (falha na leitura do filtro de entrada SSL) e AH00567 (solicitação falhou: erro ao ler os cabeçalhos). Isso pode não explicar todos os problemas.
  • solicitações de clientes malformadas, não incomuns no passado (por exemplo, CR / LF extra após o POST, solicitações incompletas ao tentar novamente após um erro). Eu não sei de nada atual, depende da sua base de clientes e, mais importante, da conectividade deles.
  • pode haver um bug semelhante a este recente que causou timeouts espúrios com "evento "MPM.

Para reproduzir tempos de espera:

 $ openssl s_client -connect myhost:443
 GET / HTTP/1.1
 Host: myhost.whatever.com 

 [server reply goes here]
 GET / HTTP/1.1
 Host:

Você pode criar scripts para facilitar, caso contrário você deve digitar / colar a primeira solicitação e os cabeçalhos dentro dos 10s configurados, depois digitar mas não concluir a segunda solicitação nos próximos 10s, você deve ter pelo menos uma linha completa (a solicitação) enviada para a segunda solicitação, depois é só esperar.

Diminuir o KeepAliveTimeout (o padrão é 5 segundos) pode ajudar. Observe que KeepAliveTimeout é o tempo para receber uma solicitação completa. Acho que o próximo passo pode ser mod_log_forensic .

Em relação às conexões com o back-end via AJP, você está usando "ping" no Apache Balancer configuration ? Se eu entendi o seu sistema corretamente, a configuração do Tomcat que você deu não se aplica a conexões do Apache httpd ao Tomcat. Veja as opções aqui .

                          /-> apache httpd + ajp -\            /-> tomcat/jboss
client -> load-balancer  <                         > firewall <
                          \-> apache httpd + ajp -/            \-> tomcat/jboss
    
por 26.03.2015 / 18:00