Setup:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache leitet Anfragen über AJP weiter.
Problem:
Nach einer bestimmten Zeitspanne (keine Konstante, kann zwischen einer oder zwei Stunden oder einem oder mehreren Tagen liegen) fällt Tomcat aus. Entweder reagiert es nicht mehr oder es wird der allgemeine "Dienst vorübergehend nicht verfügbar" angezeigt.
Diagnose:
Es gibt zwei Server mit demselben Setup. Eine Website hat einen höheren Traffic (mehrere Anfragen pro Sekunde), die andere einen niedrigen Traffic (eine Handvoll Anfragen alle paar Minuten). Beide Websites sind völlig unterschiedliche Codebasen, weisen jedoch ähnliche Probleme auf.
Wenn auf dem ersten Server das Problem auftritt, werden alle Threads langsam ausgelastet, bis das Limit erreicht ist (MaxThreads 200). Zu diesem Zeitpunkt reagiert der Server nicht mehr (und ruft nach einer langen Zeit die Seite auf, auf der der Dienst nicht verfügbar ist).
Wenn auf dem zweiten Server das Problem auftritt, dauern die Anforderungen sehr lange. Wenn sie erledigt sind, wird nur die Seite "Dienst nicht verfügbar" angezeigt.
Abgesehen von der Erwähnung des MaxThreads-Problems weisen die Tomcat-Protokolle nicht auf bestimmte Probleme hin, die dies verursachen könnten.
In den Apache-Protokollen sehen wir jedoch zufällige Nachrichten, die sich auf AJP beziehen. Hier ist ein Beispiel einer zufälligen Nachricht, die wir sehen (in keiner bestimmten Reihenfolge):
[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)
Die andere seltsame Sache, die wir auf dem Server mit höherem Datenverkehr bemerkt haben, ist, dass Datenbankabfragen viel länger dauern, bevor das Problem auftritt (2000-5000 ms im Vergleich zu normalerweise 5-50 ms). Dies dauert nur 2-4 Sekunden, bevor die MaxThreads-Meldung angezeigt wird. Ich gehe davon aus, dass dies darauf zurückzuführen ist, dass der Server plötzlich zu viele Daten / Datenverkehr / Threads verarbeitet.
Hintergrundinformation:
Diese beiden Server liefen schon länger ohne Probleme. Die Systeme wurden während dieser Zeit jeweils mit zwei Netzwerkkarten eingerichtet. Sie trennten internen und externen Verkehr. Nach einem Netzwerk-Upgrade haben wir diese Server auf einzelne Netzwerkkarten verschoben (dies wurde uns aus Gründen der Sicherheit und Einfachheit empfohlen). Nach dieser Änderung hatten die Server diese Probleme.
Lösung:
Die naheliegende Lösung besteht darin, wieder zwei Netzwerkkarten einzurichten. Die Probleme dabei sind, dass es einige Komplikationen bei der Netzwerkeinrichtung verursachen würde, und es scheint, als würde das Problem ignoriert. Wir würden es vorziehen, zu versuchen, es auf einem einzelnen NIC-Setup zum Laufen zu bringen.
Das Durchsuchen der verschiedenen Fehlermeldungen brachte nichts Nützliches (entweder alte Lösungen oder nichts mit unserem Problem zu tun).
Wir haben versucht, die verschiedenen Zeitüberschreitungen anzupassen, aber dies hat dazu geführt, dass der Server vor dem Tod etwas länger lief.
Wir sind nicht sicher, wo wir das Problem weiter diagnostizieren sollen. Wir fassen immer noch nach Strohhalmen, an denen das Problem liegen könnte:
1) Das Setup mit AJP und Tomcat ist falsch oder veraltet (dh bekannte Fehler?)
2) Das Netzwerk-Setup (zwei Netzwerkkarten gegen eine Netzwerkkarte) verursacht Verwirrung oder Durchsatzprobleme.
3) Die Websites selbst (es gibt keinen gemeinsamen Code, es werden keine Plattformen verwendet, nur grundlegender Java-Code mit Servlets und JSP)
Update 1:
Nach dem hilfreichen Rat von David Pashley habe ich während des Problems einen Stack-Trace / Thread-Dump durchgeführt. Was ich fand, war, dass sich alle 200 Threads in einem der folgenden Zustände befanden:
"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]
Seltsamerweise befand sich nur ein Thread von allen 200 Threads in diesem Zustand:
"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]
Möglicherweise zwingt der Oracle-Treiber in diesem Thread alle anderen Threads, auf den Abschluss zu warten. Aus irgendeinem Grund muss es in diesem Lesezustand hängen bleiben (der Server stellt sich niemals von selbst wieder her, es ist ein Neustart erforderlich).
Dies deutet darauf hin, dass es sich entweder um ein Netzwerk zwischen dem Server und der Datenbank oder um die Datenbank selbst handeln muss. Wir setzen unsere Diagnosemaßnahmen fort, aber alle Tipps wären hilfreich.