Configuração:
Fedora 8
Apache 2.2.8
Tomcat 5,5,8
O Apache está encaminhando solicitações usando o AJP.
Problema:
Depois de um certo período de tempo (sem constante, pode ser entre uma ou duas horas, ou um ou mais dias), o Tomcat irá para baixo. Ele pára de responder ou coloca o 'Serviço temporariamente indisponível' genérico.
Diagnóstico:
Existem dois servidores com a mesma configuração. Um abriga um site de tráfego maior (várias solicitações por segundo), o outro um tráfego baixo (um punhado de solicitações a cada poucos minutos). Ambos os websites são bases de código completamente diferentes, mas exibem problemas semelhantes.
No primeiro servidor, quando o problema ocorre, todos os threads começam lentamente a ser ocupados até atingir o limite (MaxThreads 200). Nesse ponto, o servidor não está mais respondendo (e exibe a página de serviço indisponível após um longo período de tempo).
No segundo servidor, quando o problema ocorre, os pedidos demoram muito tempo e, quando terminam, tudo o que você vê é a página de serviço indisponível.
Além da menção ao problema do MaxThreads, os logs do Tomcat não indicam problemas específicos que poderiam estar causando isso.
No entanto, nos logs do Apache, estamos vendo mensagens aleatórias referentes ao AJP. Aqui está uma amostra de mensagem aleatória que vemos (em nenhuma 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 logo antes de o problema começar a acontecer, as consultas de banco de dados estão demorando muito mais tempo do que antes (2000-5000 ms versus normalmente 5-50ms). Isso dura apenas 2 a 4 segundos antes que a mensagem MaxThreads apareça. Eu estou supondo que este é um resultado do servidor de repente, lidando com muitos dados / tráfego / threads.
Informações básicas:
Esses dois servidores estavam funcionando sem problemas há algum tempo. Na verdade, os sistemas foram configurados usando dois NICs durante esse período. Eles separaram o tráfego interno e externo. Após uma atualização de rede, movemos esses servidores para NICs individuais (isso foi recomendado para nós por motivos de segurança / simplicidade). Depois dessa mudança, os servidores começaram a ter esses problemas.
Resolução:
A solução óbvia seria voltar para uma configuração de dois NICs. Os problemas com isso são que isso causaria algumas complicações com a configuração da rede e parece ignorar o problema. Preferimos tentar executá-lo em uma única configuração de NIC.
Pesquisando as várias mensagens de erro não forneceu nada de útil (soluções antigas ou não relacionadas ao nosso problema).
Tentamos ajustar os vários tempos limites, mas isso fez com que o servidor funcionasse um pouco mais antes de morrer.
Não temos certeza de onde procurar para diagnosticar o problema ainda mais. Ainda estamos nos agarrando ao que o problema poderia ser:
1) A configuração com o AJP e o Tomcat está incorreta ou desatualizada (ou seja, erros conhecidos?)
2) A configuração da rede (dois NICs versus um 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 eu descobri foi que todos os 200 segmentos 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 segmento de todos os 200 segmentos 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 aguardarem a conclusão. Por alguma razão, é preciso estar preso neste estado de leitura (o servidor nunca se recupera sozinho, requer uma reinicialização).
Isso sugere que ele deve estar relacionado à rede entre o servidor e o banco de dados ou o próprio banco de dados. Estamos continuando os esforços de diagnóstico, mas qualquer sugestão seria útil.