La mia app Web Java con Tomcat (7.0.28) periodicamente non risponde. Sto sperando in qualche suggerimento su possibili colpevoli (sincronizzazione?), Così come forse alcuni strumenti consigliati per raccogliere maggiori informazioni su ciò che sta accadendo durante un incidente. Alcuni fatti che ho accumulato:L'app Web Java in tomcat si blocca periodicamente
Quando il web app si blocca, Tomcat continua ad alimentare le discussioni richiesta in app, ma l'applicazione non li rilascia. Il pool di thread si riempie fino al massimo (attualmente 250), quindi le richieste successive vengono immediatamente interrotte. Durante il normale funzionamento, non ci sono mai più di 2 o 3 thread attivi.
Non ci sono errori o eccezioni di alcun tipo registrati a nessuno dei nostri registri delle applicazioni Web o Tomcat quando si verifica il problema.
Fare un "Stop" e quindi un "Start" sulla nostra applicazione tramite l'app web di gestione di Tomcat risolve immediatamente questo problema (fino ad oggi).
Ultimamente la frequenza è stata due o tre volte al giorno, anche se oggi era molto peggio, probabilmente 20 volte, e talvolta non tornava alla vita immediatamente.
Il problema si verifica solo durante l'orario lavorativo
Il problema non si verifica sul nostro sistema di stadiazione
Quando si verifica il problema, utilizzo del processore e della memoria sul server rimane piatta (e piuttosto bassa) . Tomcat segnala un sacco di memoria libera.
Tomcat continua a rispondere quando si verifica il problema. L'app Web di gestione funziona perfettamente e Tomcat continua a inviare richieste nella nostra app fino a quando non vengono riempite tutte le discussioni nel pool.
Il nostro server di database rimane reattivo quando si verifica il problema. Usiamo il framework Spring per l'accesso ai dati e l'iniezione.
Il problema si verifica generalmente quando l'utilizzo è elevato, ma non c'è mai un picco insolitamente elevato nell'utilizzo.
Cronologia problemi: qualcosa di simile si è verificato circa un anno e mezzo fa. Dopo molte modifiche alla configurazione e al codice del server, il problema è scomparso fino a circa un mese fa. Nelle ultime settimane si è verificato molto più frequentemente, una media di 2 o 3 volte al giorno, a volte più volte di seguito.
Ho identificato alcuni codici server oggi che potrebbero non essere stati protetti da thread e ho inserito una correzione per questo, ma il problema si verifica ancora (anche se meno frequentemente). È questo il tipo di problema che può causare un codice non protetto da un codice?
UPDATE: Con diversi messaggi che suggeriscono connessione al database piscina esaurimento, ho fatto qualche ricerca in questa direzione e ha trovato questo altro Stackoverflow question che spiega quasi tutti i problemi che sto vivendo.
Apparentemente, i valori predefiniti per le connessioni maxActive e maxIdle nell'implementazione di BasicDataSource di Apache sono ciascuno 8. Inoltre, maxWait è impostato su -1, quindi quando il pool è esaurito e una nuova richiesta di connessione arriva, attende per sempre senza registrare alcun tipo di eccezione.Sto ancora aspettando che questo problema si ripresenti ed eseguo un jstack dump sulla JVM in modo da poter analizzare tali informazioni, ma sembra che questo sia il problema. L'unica cosa che non spiega è perché a volte l'app non si risolve da questo problema. Suppongo che le richieste si accumulino a volte e una volta che le cose non sono riuscite a raggiungerlo.
UPDATE II: mi passò una jstack durante un incidente e ha trovato circa 250 (fili max) delle seguenti operazioni:
"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)
Al mio occhio non addestrato, questo sembra abbastanza conclusiva. Sembra che il pool di connessione del database abbia raggiunto il suo limite. Ho configurato un maxWait di tre secondi senza modificare maxActive e maxIdle solo per garantire che iniziamo a vedere le eccezioni registrate quando il pool si riempie. Quindi imposterò quei valori su qualcosa di appropriato e monitor.
UPDATE III: Dopo aver configurato maxWait, ho cominciato a vedere questi nei miei ceppi, come ci si aspettava:
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)
ho impostato maxActive a -1 (infinito) e maxIdle a 10. Lo farò monitorare per un po ', ma la mia ipotesi è che questa è la fine del problema.
'kill -3' è tuo amico. Esegui questo e guarda il dump del thread. Potrebbe essere utile dare un'occhiata al Thread Dump Analyzer per il raggruppamento delle informazioni (http://java.net/projects/tda/). –
mindas
Wild-guess senza altre informazioni (sono necessari dump di thread!): Esaurimento del pool di connessioni DB. –
Questo è esattamente quello che mi stava succedendo, l'applicazione web è diventata troppo grande, le connessioni massime erano troppo basse e il tempo di attesa era indeterminato, i thread continuavano ad accumularsi e quindi il server si bloccava. Aumentati i minimi e impostare un tempo specifico in attesa massima e ora sto solo monitorando, ma il server funziona bene. Grazie per questo mini tutorial. – Lauro182