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.
quelle
Antworten:
Es stellt sich heraus, dass diese Version (Klassen 12 - ziemlich alt) des Oracle-Treibers verschiedene Fehler enthielt, die einen Deadlock verursachten (wie im oben genannten TP-Processor2-Status zu sehen). Es wurde erst aktiv, als wir auf die neue Umgebung umgestiegen sind. Durch das Aktualisieren auf die neueste Version (ojdbc14) wurde das Problem auf dem Primärserver behoben.
quelle
Aus der Beschreibung geht hervor, dass das Problem möglicherweise darauf zurückzuführen ist, dass die Datenbankabfragen zu lange dauern. Wenn die Abfragen länger dauern, dauert die Anforderung länger und daher werden mehr Abfragen gleichzeitig ausgeführt. Wie Sie sehen, gehen Ihnen die Kater-Threads aus. Wenn Sie das Problem mit der Datenbank lösen, sollten Sie in Ordnung sein.
quelle
Fügen Sie connectionTimeout und keepAliveTimeout zu Ihrem AJP-Connector hinzu, der sich in /etc/tomcat7/server.xml befindet.
Informationen zum AJP-Connector finden Sie unter https://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html
connectionTimeout = Die Anzahl der Millisekunden, die dieser Connector nach dem Akzeptieren einer Verbindung auf die Anzeige der Anforderungs-URI-Zeile wartet. Der Standardwert für AJP-Protokollconnectors ist -1 (dh unendlich).
keepAliveTimeout = Die Anzahl der Millisekunden, die dieser Connector auf eine weitere AJP-Anforderung wartet, bevor die Verbindung geschlossen wird. Der Standardwert ist die Verwendung des Werts, der für das connectionTimeout-Attribut festgelegt wurde.
Wenn die Werte connectionTimeout und keepAliveTimeout nicht definiert sind, werden AJP-Verbindungen unendlich lange am Leben erhalten. Aufgrund vieler Threads beträgt die Standard-Maximalanzahl 200.
Ich empfehle die Installation von psi-probe - einem erweiterten Manager und Monitor für Apache Tomcat, der von Lambda Probe bereitgestellt wird. https://code.google.com/p/psi-probe/
quelle
Aufgrund der Funktionsweise von AJP können die dauerhaften Verbindungen zwischen Apache (entweder mit mod_proxy_ajp oder mod_jk) nur vom Client sicher geschlossen werden . In diesem Fall ist der Client der Apache-Worker, der geöffnet wird, und hält dann eine Verbindung zu Tomcat für das Leben für den Worker-Prozess .
Aufgrund dieses Verhaltens können Sie nicht mehr Apache-Worker als Tomcat-Worker-Threads haben. Andernfalls können zusätzliche http-Worker keine Verbindung zu Tomcat herstellen (da die Annahmewarteschlange voll ist), und Ihr Backend wird als DOWN markiert!
quelle
Ich habe mit mod_proxy bessere Ergebnisse erzielt als mit mod_ajp in Bezug auf die Stabilität. Probieren Sie diese Lösung aus. Es ist nicht invasiv - bestenfalls löst es das Problem und schlimmstenfalls schließt es mod_ajp aus.
Abgesehen davon hört es sich so an, als würden Ihre Tomcats nicht mehr reagieren und alle Anfragethreads sind blockiert. Lassen Sie Ihr Entwicklerteam untersuchen, was gerade passiert. Es ist hilfreich , einen Thread-Dump zu erstellen und an sie zu senden.
quelle
Das erste, woran ich denke, wenn ich höre, dass ein Server eine Weile läuft, plötzlich langsamer wird und dann Dienstausfälle auftreten, ist, dass ihm der Arbeitsspeicher ausgeht und der Swap ausgeht. Ich bin mir nicht sicher, ob die AJP-Fehler, die Sie sehen, auf Zeitüberschreitungen zurückzuführen sein könnten, aber es scheint nicht völlig unvernünftig zu sein. Ich sehe jedoch keine offensichtliche Möglichkeit, eine Verbindung zur Netzwerkkarte herzustellen. In jedem Fall empfehle ich Ihnen, sich ein Bild davon zu machen, was mit Ihrer Speichernutzung passiert, wenn diese Ereignisse eintreten.
Wenn Ihnen der Arbeitsspeicher ausgeht, müssen Sie möglicherweise Ihren Apache herunterfahren
MaxClients
und Ihren erhöhenListenBacklog
.Übrigens, vielen Dank, dass Sie Ihre Frage so gut organisiert und vollständig gestellt haben.
quelle
Ich hatte ähnliche Protokollfehler in der Redhat-Umgebung mit proxy_ajp und Tomcat. Behebung durch Aktualisierung des httpd-Pakets:
von:
zu:
Starten Sie dann Apache neu, gefolgt von Tomcat.
Das hat es für mich behoben!
quelle