Java web app w tomcat okresowo zawiesza się

Moja aplikacja internetowa Java z Tomcat (7.0.28) okresowo przestaje odpowiadać. Liczę na jakieś sugestie ewentualnych sprawców (synchronizacja?), a także może Zalecane narzędzia do zbierania więcej informacji o tym, co dzieje się podczas awarii. Kilka faktów, które zgromadziłem:

  • Gdy aplikacja internetowa zawiesza się, tomcat kontynuuje przesyłanie wątków żądań do aplikacji, ale aplikacja nie zwalnia ich. Pula wątków wypełnia się do maksimum (obecnie 250), a następnie kolejne żądania natychmiast zawodzą. Podczas normalnej pracy nigdy nie ma więcej niż 2 lub 3 aktywnych wątków.

  • Nie ma żadnych błędów ani WYJĄTKÓW jakiegokolwiek rodzaju rejestrowanych w naszym dzienniku tomcat lub aplikacji internetowej, gdy wystąpi problem.

  • Wykonanie "Stop", a następnie "Start" w naszej aplikacji za pośrednictwem aplikacji internetowej tomcat management natychmiast rozwiązuje ten problem (do dziś).

  • Ostatnio częstotliwość ta jest dwa lub trzy razy dziennie, choć dzisiaj było znacznie gorzej, prawdopodobnie 20 razy, a czasami nie wraca do życia od razu.

  • Problem występuje tylko w godzinach pracy

  • Problem nie występuje w naszym systemie postoju

  • Gdy wystąpi problem, zużycie procesora i pamięci na serwerze pozostaje płaskie (i dość niskie). Tomcat zgłasza mnóstwo wolnej pamięci.

  • Tomcat nadal reaguje na problem. Aplikacja internetowa do zarządzania działa doskonale, a tomcat kontynuuje wysyłanie zapytań do naszej aplikacji, dopóki wszystkie wątki w Puli nie zostaną wypełnione.

  • Nasz serwer bazy danych pozostaje elastyczny, gdy wystąpi problem. Używamy Spring framework do dostępu do danych i wtrysku.

  • Problem zazwyczaj występuje, gdy użycie jest wysokie, ale nigdy nie ma niezwykle wysoki skok w użyciu.

  • Historia problemu: coś podobnego wydarzyło się około półtora roku temu. Po wielu konfiguracjach serwera i kodzie zmiany, problem zniknął dopiero około miesiąc temu. W ciągu ostatnich kilku tygodni występuje znacznie częściej, średnio 2 lub 3 razy dziennie, czasami kilka razy z rzędu.

  • Zidentyfikowałem dzisiaj jakiś kod serwera, który może nie był threadsafe, i wstawiłem do tego poprawkę, ale problem nadal występuje(choć rzadziej). Czy to jest problem, który może powodować kod un-threadsafe?

UPDATE: With several posts sugerując wyczerpanie puli połączeń z bazą danych, przeszukałem trochę w tym kierunku i znalazłem inne pytanie Stackoverflow , które wyjaśnia prawie wszystkie problemy, których doświadczam.

Domyślne wartości dla połączeń maxActive i maxIdle w podstawowej implementacji Apache ' a to 8. Ponadto maxWait jest ustawiony na -1, więc gdy pula zostanie wyczerpana i pojawi się nowe żądanie połączenia, będzie czekać w nieskończoność bez rejestrowania żadnego rodzaju wyjątek. Nadal będę czekać, aż ten problem się powtórzy i wykonam zrzut jstack na JVM, aby móc analizować te informacje, ale wygląda na to, że to jest problem. Jedyną rzeczą, której nie wyjaśnia, jest to, dlaczego aplikacja czasami nie odzyskuje tego problemu. Przypuszczam, że prośby czasami się kumulują, a gdy już się za nimi znajdą, nigdy ich nie dogonią.

UPDATE II: uruchomiłem jstack podczas awarii i znalazłem około 250 (max wątków) z "po": {]}

"http-nio-443-exec-294" daemon prio=10 tid=0x00002aaabd4ed800 nid=0x5a5d in Object.wait() [0x00000000579e2000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118)
        - locked <0x0000000743116b30> (a org.apache.commons.pool.impl.GenericObjectPool$Latch)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
        at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:718)
Dla mojego niewprawnego oka wygląda to dość rozstrzygająco. Wygląda na to, że pula połączeń bazy danych osiągnęła swój pułap. Skonfigurowałem maxWait trzech sekund bez modyfikowania maxActive i maxIdle tylko po to, aby upewnić się, że zaczynamy widzieć wyjątki rejestrowane, gdy pula zapełnia się. Następnie ustawię te wartości na coś odpowiedniego i monitoruję.

UPDATE III: Po skonfigurowaniu maxWait zacząłem je widzieć w moich logach, jako oczekiwano:

 org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
        at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)

Ustawiłem maxActive na -1 (nieskończony) i maxIdle na 10. Będę monitorował przez jakiś czas, ale moim zdaniem to koniec problemu.

Author: Community, 2012-07-12

1 answers

Z doświadczenia warto przyjrzeć się implementacji puli połączeń bazy danych. Możliwe, że baza danych ma dużą pojemność, ale Pula połączeń w aplikacji jest ograniczona do niewielkiej liczby połączeń. Nie pamiętam szczegółów, ale wydaje mi się, że miałem podobny problem, który był jednym z powodów, dla których przełączyłem się na użycie BoneCP, które okazało się bardzo szybkie i niezawodne w testach obciążenia.

Po próbie debugowania sugerowane poniżej, spróbuj zwiększyć liczbę połączeń dostępnych w Puli i sprawdź, czy ma to jakikolwiek wpływ.

Zidentyfikowałem dzisiaj jakiś kod serwera, który może nie być threadsafe, i włożę w to poprawkę, ale problem nadal się dzieje (choć rzadziej). Czy jest to rodzaj problemu, który kod un-threadsafe może spowodować?

To zależy co masz na myśli przez thread-safe. Wydaje mi się, że Twoja aplikacja powoduje, że wątki impas . Możesz uruchomić środowisko produkcyjne z JVM skonfigurowanym tak, aby umożliwić połączenie debuggera, a następnie użyć JVisualVM, JConsole lub innego narzędzia do profilowania (Twój zestaw jest doskonały IMO), aby zobaczyć, jakie masz wątki i na co czekają.

 12
Author: EngineerBetter_DJ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 08:07:19