Configuração:
Fedora 8
Apache 2.2.8 O
Tomcat 5.5.8
Apache está encaminhando solicitações usando o AJP.
Problema:
Após um determinado período de tempo (nenhuma constante, pode ocorrer entre uma hora ou duas ou um ou mais dias) o Tomcat será desativado. Ele para de responder ou coloca o genérico 'Serviço temporariamente indisponível'.
Diagnóstico:
Existem dois servidores com a mesma configuração. Um abriga um site de tráfego mais alto (várias solicitações por segundo) e o outro, um de baixo tráfego (um punhado de solicitações a cada poucos minutos). Ambos os sites são bases de código completamente diferentes, mas apresentam problemas semelhantes.
No primeiro servidor, quando o problema ocorre, todos os threads começam a ser ocupados lentamente até atingir o limite (MaxThreads 200). Nesse ponto, o servidor não está mais respondendo (e aparece com a página de serviço indisponível após um longo período de tempo).
No segundo servidor, quando o problema ocorre, as solicitações demoram muito tempo e, quando concluídas, tudo o que você vê é a página de serviço indisponível.
Além da menção ao problema MaxThreads, os logs do Tomcat não indicam nenhum problema específico que possa estar causando isso.
No entanto, nos logs do Apache, estamos vendo mensagens aleatórias referentes ao AJP. Aqui está um exemplo de mensagem aleatória que vemos (sem ordem específica):
[error] (70007)The timeout specified has expired: ajp_ilink_receive() can't receive header
[error] (104)Connection reset by peer: ajp_ilink_receive() can't receive header
[error] proxy: AJP: disabled connection for (localhost)
[error] ajp_read_header: ajp_ilink_receive failed
[error] (120006)APR does not understand this error code: proxy: read response failed from 127.0.0.1:8009 (localhost)
[error] ap_proxy_connect_backend disabling worker for (localhost)
A outra coisa estranha que notamos no servidor de tráfego mais alto é que, imediatamente antes do problema começar, as consultas ao banco de dados estão demorando muito mais do que antes (2000-5000 ms versus normalmente 5-50ms). Isso dura apenas 2-4 segundos antes que a mensagem MaxThreads seja exibida. Estou assumindo que isso é resultado do servidor de repente lidar com muitos dados / tráfego / threads.
Informações de plano de fundo:
Esses dois servidores estavam em execução sem problemas há algum tempo. Os sistemas foram realmente configurados, cada um usando duas placas de rede durante esse período. Eles separaram o tráfego interno e o externo. Após uma atualização de rede, movemos esses servidores para NICs únicas (isso nos foi recomendado por motivos de segurança / simplicidade). Após essa alteração, os servidores começaram a ter esses problemas.
Resolução:
a solução óbvia seria retornar à configuração de duas NICs. Os problemas com isso são que isso causaria algumas complicações na configuração da rede e parece ignorar o problema. Preferimos tentar executá-lo em uma única configuração de NIC.
Pesquisar as várias mensagens de erro no Google não forneceu nada de útil (soluções antigas ou não relacionadas ao nosso problema).
Tentamos ajustar os vários tempos limite, mas isso fez com que o servidor funcionasse um pouco mais antes de morrer.
Não temos certeza de onde procurar para diagnosticar mais o problema. Ainda estamos tentando entender qual seria o problema:
1) A configuração com o AJP e o Tomcat está incorreta ou desatualizada (ou seja, erros conhecidos?)
2) A configuração da rede (duas NICs versus uma NIC) está causando problemas de confusão ou taxa de transferência.
3) Os sites em si (não há código comum, nenhuma plataforma sendo usada, apenas código Java básico com servlets e JSP)
Atualização 1:
Seguindo o conselho útil de David Pashley, fiz um despejo de rastreamento / thread de pilha durante o problema. O que descobri foi que todos os 200 threads estavam em um dos seguintes estados:
"TP-Processor200" daemon prio=1 tid=0x73a4dbf0 nid=0x70dd waiting for monitor entry [0x6d3ef000..0x6d3efeb0]
at oracle.jdbc.pool.OracleConnectionCacheImpl.getActiveSize(OracleConnectionCacheImpl.java:988)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]
"TP-Processor3" daemon prio=1 tid=0x08f142a8 nid=0x652a waiting for monitor entry [0x75c7d000..0x75c7ddb0]
at oracle.jdbc.pool.OracleConnectionCacheImpl.getConnection(OracleConnectionCacheImpl.java:268)
- waiting to lock <0x7e3455a0> (a oracle.jdbc.pool.OracleConnectionCacheImpl)
[further stack trace removed for brevity]
Curiosamente, apenas um thread de todos os 200 threads estava neste estado:
"TP-Processor2" daemon prio=1 tid=0x08f135a8 nid=0x6529 runnable [0x75cfe000..0x75cfef30]
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Unknown Source)
at oracle.net.ns.DataPacket.receive(Unknown Source)
at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
[further stack trace removed for brevity]
Pode ser que o driver Oracle neste encadeamento esteja forçando todos os outros encadeamentos a aguardar a conclusão. Por alguma razão, ele deve estar preso nesse estado de leitura (o servidor nunca se recupera sozinho, é necessário reiniciar).
Isso sugere que ele deve estar relacionado à rede entre o servidor e o banco de dados ou ao próprio banco de dados. Continuamos os esforços de diagnóstico, mas qualquer dica seria útil.
fonte
Respostas:
Acontece que esta versão (classes12 - bastante antiga) do driver Oracle tinha vários bugs que causavam um conflito (como visto no estado do TP-Processor2 citado acima). Ele não se tornou ativo até mudarmos para o novo ambiente. A atualização para a versão mais recente (ojdbc14) resolveu o problema no servidor principal.
fonte
A partir da descrição, sugiro que o problema seja devido às consultas do banco de dados que demoram muito tempo. Se as consultas estiverem demorando mais, a solicitação demorará mais e, portanto, você terá mais delas em execução ao mesmo tempo. Como você vê, está ficando sem threads do tomcat. Ao resolver o problema com o banco de dados, você deve ficar bem.
fonte
Adicione connectionTimeout e keepAliveTimeout ao seu conector AJP encontrado em /etc/tomcat7/server.xml.
Informações sobre o conector AJP em https://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html
connectionTimeout = O número de milissegundos que este Conector aguardará, após aceitar uma conexão, para que a linha URI da solicitação seja apresentada. O valor padrão para os conectores do protocolo AJP é -1 (ou seja, infinito).
keepAliveTimeout = O número de milissegundos que este Conector aguardará por outra solicitação de AJP antes de fechar a conexão. O valor padrão é usar o valor que foi definido para o atributo connectionTimeout.
Se os valores connectionTimeout e keepAliveTimeout não estiverem definidos, as conexões AJP serão mantidas ativas por infinito. Causando muitos threads, o número máximo de threads padrão é 200.
Eu recomendo instalar o psi-probe - um gerenciador e monitor avançado do Apache Tomcat, bifurcado do Lambda Probe. https://code.google.com/p/psi-probe/
fonte
Devido à maneira como o AJP funciona, as conexões persistentes entre o apache (usando mod_proxy_ajp ou mod_jk) só podem ser fechadas com segurança pelo cliente . Nesse caso, o cliente é o trabalhador apache que é aberto e mantém uma conexão com o tomcat durante toda a vida útil do processo do trabalhador .
Devido a esse comportamento, você não pode ter mais trabalhadores apache do que os threads de trabalhadores do tomcat. Isso fará com que trabalhadores http adicionais falhem na conexão com o tomcat (como a fila de aceitação está cheia) e marcará seu back-end como BAIXO!
fonte
Eu tive melhores resultados com mod_proxy em vez de mod_ajp em termos de estabilidade, então tente essa solução. É não invasivo - na melhor das hipóteses, resolverá o problema e, na pior, excluirá o mod_ajp.
Além disso, parece que o seu Tomcats para de responder e todos os threads de solicitação são amarrados. Peça à sua equipe de desenvolvimento o que está acontecendo - pegar um despejo de threads e entregá-lo a eles será útil.
fonte
A primeira coisa que penso quando ouço que um servidor é executado por um tempo, diminui de repente e começa a ter falhas de serviço é que ele está ficando sem memória RAM e trocando trocas. Não estou claro se as falhas do AJP que você está vendo podem ser conseqüentes de tempos limite, mas não parece completamente irracional; não vejo nenhuma maneira óbvia de se conectar à NIC. De qualquer forma, recomendo que você tenha uma imagem do que está acontecendo com o uso da memória quando esses eventos acontecem.
Se você está ficando sem memória RAM, pode precisar desligar o Apache
MaxClients
e aumentar o seuListenBacklog
.A propósito, obrigado por tornar sua pergunta tão bem organizada e completa.
fonte
Eu tive erros de log semelhantes no ambiente Redhat com proxy_ajp e Tomcat. Resolvido atualizando o pacote httpd:
a partir de:
para:
Em seguida, reiniciei o apache, seguido pelo Tomcat.
Isso consertou para mim!
fonte