2010-02-11 30 views
10

Ho (il più recente) jdk 1.6.0.18 si blocca mentre si esegue un'applicazione Web (il più recente) tomcat 6.0.24 in modo imprevisto dopo 4 a 24 ore 4 ore a 8 giorni di stress test (30 thread che colpiscono l'app a 6 milioni di pagine/giorno). Questo è su RHEL 5.2 (Tikanga).JVM si arresta in modo anomalo su RHEL 5.2

La relazione crash è a http://pastebin.com/f639a6cf1 ei coerenti parti del crollo sono:

  • un SIGSEGV viene gettata
  • su libjvm.so
  • spazio Eden è sempre pieno (100%)

JVM viene eseguito con le seguenti opzioni:

CATALINA_OPTS="-server -Xms512m -Xmx1024m -Djava.awt.headless=true" 

Ho anche testato la memoria per problemi hardware utilizzando http://memtest.org/ per 48 ore (14 passaggi dell'intera memoria) senza errori.

Ho abilitato -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps per controllare eventuali tendenze del GC o esaurimento dello spazio, ma non c'è nulla di sospetto lì. GC e GC completo avvengono a intervalli prevedibili, liberando quasi sempre la stessa quantità di capacità di memoria.

La mia applicazione non utilizza direttamente alcun codice nativo.

Qualche idea su dove dovrei guardare dopo?

Edit - maggiori informazioni:

1) Non v'è alcun vm cliente in questo JDK:

[[email protected] ~]$ java -version -server 
java version "1.6.0_18" 
Java(TM) SE Runtime Environment (build 1.6.0_18-b07) 
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode) 

[[email protected] ~]$ java -version -client 
java version "1.6.0_18" 
Java(TM) SE Runtime Environment (build 1.6.0_18-b07) 
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode) 

2) Modifica della O/S non è possibile.

3) Non voglio modificare le variabili di stress test JMeter poiché questo potrebbe nascondere il problema. Dal momento che ho un caso d'uso (lo scenario di stress test attuale) che blocca la JVM vorrei correggere l'incidente e non cambiare il test.

4) Ho fatto static analysis sulla mia applicazione ma non è venuto fuori nulla di serio.

5) La memoria non cresce nel tempo. L'utilizzo della memoria si bilancia molto rapidamente (dopo l'avvio) con una tendenza molto costante che non sembra sospetta.

6)/var/log/messaggi non contiene alcuna informazione utile, prima o durante il momento del crash

Maggiori informazioni: dimenticato di dire che c'era un apache (2.2.14) Tomcat fronteggia usando mod_jk 1.2.28. In questo momento sto eseguendo il test senza apache nel caso in cui l'arresto JVM si riferisca al codice nat_jk mod_jk che si connette a JVM (connettore tomcat).

Successivamente (se JVM si arresta di nuovo) proverò a rimuovere alcuni componenti dalla mia applicazione (caching, lucene, quarzo) e più avanti proverò a usare il molo. Poiché l'incidente si verifica attualmente in qualsiasi momento tra 4 ore e 8 giorni, potrebbe essere necessario molto tempo per scoprire cosa sta succedendo.

+1

Questo deve andare a Sun Oracle. – bmargulies

+0

@bmargulies: Questo è quello a cui inizialmente pensavo, ma poi ho letto http://stackoverflow.com/questions/1353514/uncuno-secondo-sottimando-hserr-files-to-sun – cherouvim

+1

Presumendo che tu usi un JDK recente, hai provato a studiare il suo comportamento in tempo reale con VisualVM? Abbiamo scoperto che è molto più efficace dei profili di terze parti a indagare sulle perdite. – Uri

risposta

4

Avete l'output del compilatore? vale a dire PrintCompilation (e se ti senti particolarmente coraggioso, LogCompilation).

Ho eseguito il debug di un caso come questo nella parte osservando ciò che il compilatore sta facendo e, alla fine (questo ha richiesto molto tempo fino al momento della lampadina), rendendosi conto che il mio crash è stato causato dalla compilazione di un particolare metodo in il driver jdbc di Oracle.

Fondamentalmente quello che vorrei fare è;

  • interruttore sul PrintCompilation
  • dal momento che non dà timestamp, scrivere uno script che guarda che file di log (come un sonno ogni secondo e stampare nuove righe) e relazioni quando i metodi sono stati compilati (o non)
  • ripetere il test
  • controllo dell'uscita compilatore per vedere se l'incidente corrisponde compilazione di qualche metodo
  • ripetere un paio di volte per vedere se v'è un modello

Se esiste un pattern riconoscibile, utilizzare .hotspot_compiler (o .hotspotrc) per impedire che compili il metodo/i incriminati, ripetere il test e vedere se non esplode. Ovviamente nel tuo caso questo processo potrebbe teoricamente richiedere mesi che ho paura.

alcuni riferimenti

L'altra cosa che farei è cambiare sistematicamente l'algoritmo di GC che si sta utilizzando e controllare gli orari di arresto nei confronti di attività gc (per esempio è correlato con un gc giovane o vecchio, che dire dei TLAB?).Il tuo discarica indica che si sta utilizzando pulisca parallelo in modo da provare

  • il (giovane) collettore di serie (IIRC può essere combinato con un vecchio parallelo)
  • ParNew + CMS
  • G1

se non si ripresenta con i vari algos di GC, allora sai che è finito (e non hai una soluzione, ma per cambiare GC algo e/o tornare indietro attraverso le JVM più vecchie finché non trovi una versione di quell'algo che non soffia).

+0

Grazie per aver portato PrintCompilation alla mia attenzione. Lo proveremo sicuramente. – cherouvim

3

alcune idee:

  • utilizzare un diverso JDK, Tomcat e/o OS versione
  • leggermente modificare i parametri del test, ad esempio 25 le discussioni a 7.2 M di pagine viste/giorno
  • Monitor o il profilo di utilizzo della memoria
  • Debug o sintonizzare il Garbage Collector
  • Esegui analisi statica e dinamica
1

La vostra memoria crescere nel corso del tempo? Se è così, ti suggerisco di cambiare i limiti di memoria più in basso per vedere se il sistema sta fallendo più frequentemente quando la memoria è esaurita.

È possibile riprodurre il problema più velocemente se:

  • si diminuisce la memoria availble per la JVM?
  • Si riducono le risorse di sistema disponibili (ad esempio, la memoria del sistema di scarico in modo che JVM non ne abbia abbastanza)
  • È possibile modificare i casi d'uso in un modello più semplice?

Una delle strategie principali che ho utilizzato è determinare quale caso d'uso sta causando il problema. Potrebbe essere un problema generico o potrebbe essere un caso specifico. Prova a registrare l'avvio e l'arresto dei casi d'uso per vedere se è possibile determinare quali casi d'uso sono più propensi a causare il problema. Se dividi a metà i casi d'uso, vedi quale metà fallisce il più veloce. È probabile che sia una causa più frequente del fallimento. Naturalmente, eseguire alcune prove di ciascuna configurazione aumenterà la precisione delle misurazioni.

ho anche stati conosciuti per cambiare sia il server per fare po 'di lavoro o di ciclo sul lavoro che il server sta facendo. Uno rende il tuo codice dell'applicazione molto più difficile, l'altro rende il server Web e il server delle applicazioni molto più difficili.

Buona fortuna, Jacob

+0

Guardando la tua traccia, la memoria di sistema non dovrebbe essere il problema in questo caso. Ci sono messaggi nel registro di sistema? Inoltre, se sto leggendo correttamente, sembra che potresti avere un numero piuttosto elevato di thread in esecuzione. Ci sono un sacco di thread in attesa della CPU disponibile in un dato momento. Mi aspetterei tempi di risposta medi più rapidi con un numero inferiore di thread. – TheJacobTaylor

1

Provare a portare il servlet container da Tomcat a Jetty http://jetty.codehaus.org/jetty/.

+0

Per vedere se la JVM andrà ancora in crash? O per migrare completamente al molo? – cherouvim

+0

Vorrei andare a migrare completamente al Jetty, solo perché mi piace quello che ho visto da Jetty in passato. Tuttavia, gli ultimi confronti che ho cercato su Google sembrano mostrare che le prestazioni Jetty-6 vs Tomcat-6 sono abbastanza simili, sebbene Jetty abbia un'impronta di memoria più leggera. Da un approccio più metodico, fintanto che l'applicazione è conforme agli standard, la migrazione non dovrebbe essere troppo difficile, e quindi si potrebbe essere in grado di eliminare il contenitore come causa principale o verificare l'applicazione come causa principale. In bocca al lupo. – crowne

+1

grazie per il commento. La mia applicazione è compatibile con tutti i principali server (tomcat, jboss, resin, jetty, glashfish), quindi la migrazione non è un problema. Proverò sicuramente lo stress test sul pontile. – cherouvim

1

Se fossi in te, farei il seguente:

  • provare un po 'più vecchie versioni/JVM Tomcat. Sembra che tu stia correndo il più nuovo e il più grande. Scenderei in due versioni o giù di lì, eventualmente provare JRockit JVM.
  • fare una discarica filo (uccidere -3 java_pid) mentre l'applicazione è in esecuzione per vedere gli stack completi. Il tuo discarica attuale mostra un sacco di discussioni in corso bloccati - ma non è chiaro da dove bloccano (I/O qualche blocco fame interno qualcos'altro???). Mi piacerebbe anche forse pianificare uccidere -3 da eseguire ogni momento a confrontare qualsiasi discarica filo casuale con quella appena prima dello schianto.
  • ho visto casi in cui Linux JDK muore proprio mentre Windows JDK è in grado di catturare con grazia un'eccezione (era StackOverflowException allora), quindi se si può modificare il codice, aggiungere "Catch Throwable" da qualche parte nella classe regina. Nel caso in cui.
  • Gioca con opzioni di ottimizzazione GC. Attiva/disattiva il GC simultaneo, regola NewSize/MaxNewSize. E sì, questo non è scientifico, piuttosto un disperato bisogno di soluzioni operative.Maggiori dettagli qui: http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html

Facci sapere come è stato risolto!

2

Hai provato hardware diverso? Sembra che tu stia usando un'architettura a 64 bit. Nella mia esperienza 32-bit è più veloce e più stabile. Forse c'è anche un problema con l'hardware. Il tempo di "tra le 4 e le 24 ore" è abbastanza diffuso per essere solo un problema di software. Sebbene tu dica che il log di sistema non ha errori, quindi potrei essere lontano. Continuo a pensare che valga la pena provare.

+0

Provare hardware diverso non è un'opzione, ma proverò il jvm a 32 bit. Grazie – cherouvim

1

È un'opzione per passare alla JVM a 32 bit? Credo che sia l'offerta più matura di Sun.

+0

Ci proveremo. Grazie. – cherouvim

Problemi correlati