O Apache Tomcat sufoca depois de 300 conexões

16

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

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

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

Eu pesquisei e encontrei várias sugestões, mas nada parece funcionar. A seguir estão algumas configurações que foram feitas diretamente dos recursos on-line.

Eu aumentei os limites de conexão máxima e de 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 várias sugestões, mas em vão ... como consertar isso? Tenho certeza que o servidor m2xlarge deve atender mais pedidos que 300, provavelmente eu poderia estar dando errado com minha configuração ..

O servidor bloqueia apenas durante o horário de pico e quando há 300 solicitações simultâneas aguardando que o serviço da Web [300 segundos atrasado] responda.

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

Eu encontrei cerca de 1000 conexões no estado TIME_WAIT, não tenho idéia do que isso significaria em termos de desempenho, tenho certeza que isso 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 há cerca de 10-15k conexões tcp para o servidor membase [local]

ALGUNS ERROS NO MODJK LOG, espero que isso forneça alguma luz sobre o problema.

[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

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

Eu também começaria a procurar em servidores baseados, como o nginx.

    
por john titus 08.07.2012 / 22:53

9 respostas

13

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

    
por 11.07.2012 / 17:45
6

Considere configurar um servidor da web de proxy assíncrono como nginx ou lighttpd na frente do Apache. O Apache exibe conteúdo de forma síncrona para que os funcionários fiquem bloqueados até que os clientes baixem o conteúdo gerado na íntegra (mais detalhes aqui ). Configurar um proxy assíncrono (sem bloqueio) geralmente melhora drasticamente a situação (eu costumava diminuir o número de trabalhadores Apache em execução simultânea de 30 para 3-5 usando nginx como proxy frontend).

    
por 11.07.2012 / 11:40
5

Eu suspeito que seu problema está no tomcat e não no apache, dos logs que você mostrou de qualquer maneira. Quando você obtém o 'erro 110' tentando se conectar de volta ao tomcat, isso indica que você tem uma fila de conexões esperando para ser atendida, que não cabe mais na configuração do backlog de escuta para o 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, esperando que algo retorne do tomcat. Eu aposto que se você tentou buscar algum conteúdo estático que é diretamente servido pelo apache (ao invés de ser proxied para o tomcat), isso funcionaria mesmo quando normalmente está 'sufocando'.

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

Ah, e talvez seja necessário considerar também a possibilidade de que os serviços de rede externa limitem o número de conexões que está fazendo para você até 300, Por isso, não faz diferença quanto a manipulação de concorrência que você está fazendo na sua frente, se praticamente todas as conexões que você faz dependem de uma resposta externa dos serviços da Web.

Em um de seus comentários, você mencionou que os dados ficam obsoletos depois de dois minutos. Sugiro o armazenamento em cache da resposta obtida desse serviço por dois minutos para reduzir a quantidade de conexões simultâneas que você está direcionando para o serviço da Web externo.

    
por 11.07.2012 / 15:48
2

O primeiro passo para solucionar isso é habilitar o mod_status do Apache e estudar seu relatório - até você Fiz isso, na verdade você está andando cegamente. Isso não é justo. ; -)

A segunda coisa a ser mencionada (eu pessoalmente não gosto de receber respostas para perguntas que eu não estava perguntando, mas ...) é usar servidores front-end mais eficientes e especiais como nginx .

Além disso, você fez exatamente restart apache ou apenas graceful ly recarregou ? :)

    
por 11.07.2012 / 17:38
1

Para qualquer tipo de implementação enterprise-y, o prefork MPM é a pior escolha que você pode fazer: engole recursos como os negócios de ninguém e o reinício de threads leva FOREVER em comparação com outros MPMs.

Mude pelo menos para o MPM worker (apache 2.2 ou superior) ou - melhor ainda - atualize para a versão estável atual 2.4.2 com seu MPM evento padrão.

Ambos irão lidar facilmente com milhares de conexões simultâneas com muito pouca sobrecarga.

    
por 10.07.2012 / 15:25
1

Eu sei que é uma história antiga, mas tenho duas observações.

Existe um limite de código fixo para a diretiva ServerLimit . link , você verá que é no máximo 20000 / 200K.

There is a hard limit of ServerLimit 20000 compiled into the server (for the prefork MPM 200000). This is intended to avoid nasty effects caused by typos.

2 Aparentemente, nodybo mencionou que definir esses 2 para um é uma idéia muito ruim :

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

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

Eu encontrei um artigo muito bom explicando isso, mas - é francês ;-) link

    
por 18.02.2016 / 22:14
0

extra large with 34GB memory.

O ferro grande não é a maneira de dimensionar o webserving, você está apenas mexendo nos gargalos. Mas mesmo com essa quantidade de memória, suspeito que 50000 conexões estejam pressionando o que o sistema é capaz, especialmente se:

During peak hours the server chokes at just about 300 httpd processes

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

Também é muito estranho ter um limite tão alto para conexões, mas um limite muito baixo para a histerese (min / max de servidores extras).

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

    
por 11.07.2012 / 13:24
0

Talvez o usuário do Apache esteja ficando sem identificadores de arquivos permitidos? Você não mencionou nada no seu post. Quantas limas de arquivos o Apache pode ter atualmente?

    
por 11.07.2012 / 17:16
0

Isso é mais como um comentário, mas não como eu tenho menos reputação. Passou por um problema exatamente semelhante ao de @john titus.

Fizemos o conector AJP MaxThreads próximo do limite do nosso Apache Thread para resolver o problema.

Para monitorar isso, procuramos 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 desceu para 0, que sempre foi um grande número antes do limite MaxThread definido no conector AJP.

    
por 11.05.2018 / 14:30