Konfiguracja:
Fedora 8
Apache 2.2.8
Tomcat 5.5.8
Apache przekazuje żądania za pomocą AJP.
Problem:
Po pewnym czasie (brak stałej, może wynosić od godziny do dwóch lub jednego lub więcej dni) Tomcat spadnie. Albo przestaje odpowiadać, albo wyświetla ogólny „Usługa tymczasowo niedostępna”.
Diagnoza:
istnieją dwa serwery z tą samą konfiguracją. Jedna z nich zawiera witrynę o wyższym natężeniu ruchu (kilka żądań na sekundę), a druga o niskim ruchu (garść żądań co kilka minut). Obie strony są zupełnie różnymi bazami kodów, ale wykazują podobne problemy.
Na pierwszym serwerze, gdy pojawia się problem, wszystkie wątki powoli zaczynają być podejmowane aż do osiągnięcia limitu (MaxThreads 200). W tym momencie serwer przestał odpowiadać (i po dłuższym czasie pojawia się strona niedostępna dla usługi).
Na drugim serwerze, gdy wystąpi problem, żądania zajmują dużo czasu, a po ich zakończeniu widać tylko stronę niedostępną dla usługi.
Poza wzmianką o problemie MaxThreads, dzienniki Tomcat nie wskazują żadnych konkretnych problemów, które mogą to powodować.
Jednak w dziennikach Apache widzimy losowe komunikaty dotyczące AJP. Oto próbka losowego komunikatu, który widzimy (bez określonej kolejności):
[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)
Inną dziwną rzeczą, którą zauważyliśmy na serwerze o wyższym natężeniu ruchu, jest to, że tuż przed wystąpieniem problemu zapytania bazy danych trwają znacznie dłużej niż wcześniej (2000-5000 ms w porównaniu z normalnie 5-50ms). Trwa to tylko 2-4 sekundy, zanim pojawi się komunikat MaxThreads. Zakładam, że jest to wynikiem nagłego radzenia sobie przez serwer ze zbyt dużą ilością danych / ruchu / wątków.
Informacje podstawowe:
Te dwa serwery działały bez problemu od dłuższego czasu. Systemy były konfigurowane za pomocą dwóch kart sieciowych w tym czasie. Rozdzielili ruch wewnętrzny i zewnętrzny. Po aktualizacji sieci przenieśliśmy te serwery do pojedynczych kart sieciowych (było to nam zalecane ze względów bezpieczeństwa / prostoty). Po tej zmianie serwery zaczęły mieć te problemy.
Rozwiązanie:
Oczywistym rozwiązaniem byłoby powrót do konfiguracji dwóch kart sieciowych. Problem polega na tym, że spowodowałoby to pewne komplikacje w konfiguracji sieci i wydaje się, że zignorowanie problemu. Wolelibyśmy spróbować uruchomić go na jednej konfiguracji karty sieciowej.
Przeglądanie różnych komunikatów o błędach nie zapewnia niczego przydatnego (ani starych rozwiązań, ani nie ma związku z naszym problemem).
Próbowaliśmy dostosować różne limity czasu, ale właśnie to spowodowało, że serwer działał nieco dłużej przed śmiercią.
Nie jesteśmy pewni, gdzie szukać dalszej diagnozy problemu. Nadal chwytamy się słomy, na czym polega problem:
1) Konfiguracja z AJP i Tomcat jest niepoprawna lub nieaktualna (tzn. Znane błędy?)
2) Konfiguracja sieci (dwie karty sieciowe i jedna karta sieciowa) powoduje problemy z pomyłką lub przepustowością.
3) Same strony internetowe (nie ma wspólnego kodu, nie używa się platform, tylko podstawowy kod Java z serwletami i JSP)
Aktualizacja 1:
Postępując zgodnie z pomocnymi wskazówkami Davida Pashleya, zrobiłem stos śledzenia / zrzutu wątku podczas problemu. Odkryłem, że wszystkie 200 wątków było w jednym z następujących stanów:
"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]
Co ciekawe, tylko jeden wątek ze wszystkich 200 wątków był w tym stanie:
"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]
Możliwe, że sterownik Oracle w tym wątku zmusza wszystkie pozostałe wątki do oczekiwania na zakończenie. Z jakiegoś powodu musi utknąć w tym stanie odczytu (serwer nigdy nie odzyskuje samodzielnie, wymaga ponownego uruchomienia).
Sugeruje to, że musi to być związane z siecią między serwerem a bazą danych lub samą bazą danych. Kontynuujemy wysiłki diagnostyczne, ale wszelkie wskazówki byłyby pomocne.