Apache Tomcat engasga após 300 conexões

16

Temos um servidor web apache na frente do Tomcat hospedado no EC2, o tipo de instância é muito grande com 34 GB de memória.

Nosso aplicativo lida com muitos serviços da web externos e temos um serviço da web externo muito ruim, que leva quase 300 segundos para responder às solicitações durante o horário de pico.

Durante o horário de pico, o servidor engasga com apenas cerca de 300 processos httpd. ps -ef | grep httpd | wc -l = 300

Pesquisei no Google e encontrei inúmeras sugestões, mas nada parece funcionar. A seguir, algumas configurações que fiz, que são obtidas diretamente dos recursos online.

Aumentei os limites de conexão máxima e clientes máximos no apache e no tomcat. Aqui estão os detalhes da configuração:

//apache

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>

// tomcat

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>

//Sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024

Eu tenho tentado inúmeras sugestões, mas em vão .. como consertar isso? Tenho certeza que o servidor m2xlarge deve atender a mais de 300 solicitações, provavelmente eu posso estar errado com a minha configuração ..

O servidor engasga somente durante o horário de pico e quando há 300 solicitações simultâneas aguardando a resposta do serviço da web [300 segundos atrasado].

Eu estava apenas monitorando as conexões TCP com o netstat

Encontrei cerca de 1000 conexões no estado TIME_WAIT, não faço ideia do que isso significaria em termos de desempenho, tenho certeza que deve estar aumentando o problema.

Saída do TOP

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48

Também no horário de pico, existem cerca de 10 a 15k conexões tcp ao servidor membase [local]

ALGUNS ERROS NO MODJK LOG, espero que isso jogue alguma luz sobre o assunto.

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600

// Resolvido

obrigado por todas as suas sugestões valiosas .. perdi as configurações maxThreads para o conector AJP 1.3 .. Agora tudo parece estar sob controle.

Eu também começaria a olhar para servidores baseados mesmo como o nginx.

john titus
fonte
Como são as configurações do Keepalive?
Tom O'Connor
Que tipo de erro os clientes retornam ao tentar carregar uma página?
Shane Madden
11
Você aumentou as descrições máximas de arquivos abertos permitidos para o usuário apache / httpd?
golja 9/07/12
@ Tom Meu Manter configurações Vivo são KeepAliveTimeout 10 em httpd.conf
John Titus
3
Como é a saída de topdurante esses tempos? Que tal free -m? E por último iostat?
Zypher

Respostas:

13

Você aumentou maxThreads no AJP 1.3 Connector na porta 8009?

HTTP500
fonte
1500 é o que eu tenho por tomcat exemplo
John Titus
@ john, você está dizendo que para cada conector que você especificou maxThreads = "1500"? Você pode publicar sua estrofe para o AJP 1.3 Connector (porta 8009)?
HTTP500
obrigado por apontar isso .. não há nenhuma configuração maxThreads para AJP1.3 .. isso poderia ser o motivo?
John Titus
11
Sim, adicione maxThreads à sub-rotina desse conector. O padrão é 200.
HTTP500
6

Considere a possibilidade de configurar um servidor da Web de proxy assíncrono como nginxou lighttpdna frente do Apache. O Apache exibe conteúdo de forma síncrona, para que os funcionários sejam bloqueados até que os clientes façam o download completo do conteúdo gerado (mais detalhes aqui ). A configuração de um proxy assíncrono (sem bloqueio) geralmente melhora drasticamente a situação (eu costumava diminuir o número de trabalhadores do Apache em execução simultânea de 30 para 3-5, usando nginxcomo proxy de front-end).

Alex
fonte
5

Eu suspeito que seu problema está no tomcat e não no apache, pelos logs que você mostrou de qualquer maneira. Quando você recebe o 'erro 110' ao tentar se conectar novamente ao tomcat, isso indica que há uma fila de conexões aguardando para serem atendidas, que não cabem mais na configuração da lista de pendências de escuta do soquete de escuta no tomcat.

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.

Se eu tivesse que adivinhar, suspeitaria que a grande maioria das solicitações HTTP quando o servidor está "bloqueando" está bloqueada, aguardando que algo volte do tomcat. Aposto que se você tentasse buscar algum conteúdo estático que é servido diretamente pelo apache (em vez de ser procurado pelo tomcat), isso funcionaria mesmo quando estivesse "sufocando" normalmente.

Infelizmente, não estou familiarizado com o tomcat, mas existe uma maneira de manipular as configurações de simultaneidade disso?

Ah, e você também pode considerar a possibilidade de que os serviços de rede externa limitem o número de conexões que ele está fazendo para você em até 300, portanto, não faz diferença a quantidade de manipulação de simultaneidade que você está fazendo na sua frente. se praticamente todas as conexões feitas forem baseadas em uma resposta externa de serviços da web.

Em um de seus comentários, você mencionou que os dados ficam obsoletos após 2 minutos. Sugiro que você armazene em cache a resposta que você recebe deste serviço por dois minutos para reduzir a quantidade de conexões simultâneas que você está dirigindo para o serviço da web externo.

Matthew Ife
fonte
2

A primeira etapa para solucionar isso é habilitar o mod_status do Apache e estudar seu relatório - até que você faça isso, na verdade você está andando cegamente. Isso não é justo. ;-)

A segunda coisa a mencionar (eu não gosto de receber respostas para perguntas que não estava fazendo, mas ...) está usando servidores front-ends mais eficientes e especiais como nginx.

Além disso, não é exatamente o restartapache, ou apenas gracefully recarregado -lo? :)

poige
fonte
Apache reiniciado .. não uma recarga graciosa
John Titus
@ johntitus, bem, mod_statusé seu amigo, de qualquer maneira. :)
poige
1

Para qualquer tipo de implantação empresarial, o MPM pré-fork é praticamente a pior escolha que você pode fazer: consome recursos como os negócios de ninguém, e reiniciar threads leva para SEMPRE em comparação com outros MPMs.

Pelo menos, mude para o MPM de trabalho (apache 2.2 ou superior) ou - melhor ainda - atualize para a versão estável atual 2.4.2 com seu evento padrão MPM.

Ambos lidam facilmente com milhares de conexões simultâneas com muito pouca sobrecarga.

adaptr
fonte
obrigado .. tentei isso também .. sem sorte. As conexões TIME_WAIT continuam aumentando. Servidor pára de responder em 350 conexões
John Titus
11
Discordo que é a pior escolha - é uma escolha ruim para esse contexto e é provável que os problemas sejam atenuados usando o servidor de threads, mas uma solução melhor seria usar um servidor baseado em eventos (nginx ou lighttpd). O Apache baseado em eventos não está maduro o suficiente para ser considerado em um IMHO de implantação corporativa.
symcbean
1

Eu sei que é uma história antiga, mas tenho 2 comentários.

Há um limite codificado para a Diretiva ServerLimit . http://httpd.apache.org/docs/2.2/mod/mpm_common.html#serverlimit, você verá que é no máximo 20000 / 200K.

Existe um limite rígido do ServerLimit 20000 compilado no servidor (para o prefork MPM 200000). Isso tem como objetivo evitar efeitos desagradáveis ​​causados ​​por erros de digitação.

Segundo, aparentemente, o nodybo mencionou que definir esses 2 para um é uma péssima idéia :

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle=1

significa que você reutiliza o timewait cedo, adivinhe? o servidor pode conversar com o cliente errado sob carga pesada.

Encontrei um artigo muito bom explicando isso, mas - é francês ;-) http://vincent.bernat.im/fr/blog/2014-tcp-time-wait-state-linux.html

Nadir
fonte
0

extra grande com 34GB de memória.

O ferro grande não é o caminho para dimensionar o serviço da Web, você está apenas movendo os gargalos. Mas, mesmo com tanta memória, suspeito que 50000 conexões estão promovendo o que o sistema é capaz, principalmente se:

Durante o horário de pico, o servidor engasga com apenas cerca de 300 processos httpd

Seria útil se você explicasse o que quer dizer com "o servidor engasga".

Também é muito estranho ter um limite tão alto para conexões, mas um limite muito baixo para histerese (servidores sobressalentes mín. / Máx.).

Embora a extração de erros que você forneceu não mostre o indicador 'muitos arquivos abertos', eu começaria examinando o número de descritores de arquivos abertos e as configurações ulimit.

symcbean
fonte
Engasga Server como em esquentar responder a arquivos de html, mesmo normais ..
John Titus
Mudei os MaxClients para 3000 agora .. ainda o mesmo problema
John Titus
0

Talvez o usuário do Apache esteja ficando sem identificadores de arquivos permitidos? Você não os mencionou na sua postagem. Quantos manipuladores de arquivos o Apache atualmente tem?

Janne Pikkarainen
fonte
128192 identificadores de arquivo
john titus
0

É mais como um comentário, mas, como não posso, tenho menos reputação. Me deparei com um problema exatamente semelhante ao do @john titus.

Tornamos o conector AJP MaxThreadspróximo ao nosso limite do Apache Thread para resolver o problema.

Para monitorar isso, procuramos a SYN_SENT ajuda do status da porta netstat com o comando netstat em nossa porta AJP.

netstat -an | grep :8102 | grep SYN_SENT | wc -l

Isso caiu para 0, que sempre foi um grande número antes do limite do MaxThread definido no AJP Connector.

Vineeth
fonte