2012-04-02 9 views
31

Ho un Tomcat 7 in esecuzione in Linux che mi metto via $CATALINA_HOME/bin/startup.sh e lo spegnimento tramite $CATALINA_HOME/bin/shutdown.sh
da /etc/init.dTomcat non si ferma. Come posso eseguire il debug di questo?

Tutto è ok tranne 1 problema. A volte Tomcat non si ferma.
Anche se lo interrompe e vedo nei cataloghi catalina.out che stanno andando giù, se faccio ps -ef posso ancora vedere il processo in esecuzione.

Quale potrebbe essere il problema? Come posso eseguire il debug di questo? La mia sensazione è che questo è legato ai thread.

Così le parti che sono sospette sono i seguenti:
1) Io uso LogManager di Log4j per rilevare se la configurazione log4j è stato modificato, ma lo faccio Log4jManager.shutdown su un contextDestroyedServletContextListener
2) Io uso H2 database e io vedi allo spegnimento:

GRAVI: L'applicazione web [/ MyApplication] sembra aver iniziato una discussione
nome [H2 Log Writer MyApplication], ma non è riuscito a fermarlo.
questo è molto probabile che creare una perdita di memoria

GRAVI: L'applicazione web [/ MyApplication] sembra aver iniziato una
filo di nome [File H2 Blocco Watchdog
/opt/myOrg/tomcat/webapps/MyApplication /db/myDatabase.lock.db] ma ha
non è riuscito a fermarlo. È molto probabile che questo crei una perdita di memoria. 2-apr-
2012 09:08:08 org.apache.catalina.loader.WebappClassLoader
clearReferencesThreads GRAVI: L'applicazione web [/ MyApplication]
sembra aver iniziato una discussione chiamato [FileWatchdog] ma non è riuscito
per fermarlo. È molto probabile che questo crei una perdita di memoria.

Qualsiasi aiuto per favore? Come posso rilevare il problema qui?

UPDATE:
ho fatto un kill -3 come suggerito da @daveb, e nel catalina.out vedo:

JVMDUMP006I Processing discarica evento "utente", particolare "" - attenda prego. JVMDUMP032I JVM richiesto Java discarica utilizzando '/etc/init.d/javacore.20120402.093922.2568.0001.txt' in risposta a un evento JVMDUMP010I Java discarica scritto /etc/init.d/javacore.20120402.093922.2568.0001.txt JVMDUMP013I Evento di dumping elaborato "utente", dettaglio "".

C'è un javacore in /etc/init.d ma non so come elaborarlo. Cioèquali parti dovrei indagare

+0

Provare a contrassegnare i thread come thread daemon in modo che la VM non aspetti la loro morte. http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#setDaemon(boolean) Ma ovviamente è utile solo per i propri thread, non per quelli avviati solo da H2 – luukes

+0

H2 crea i thread demone. –

+0

@ThomasMueller: Allora, sembra che il 'SEVERE: L'applicazione web [/ MYAPPLICATION] abbia avviato un thread chiamato [H2 File Lock Watchdog /opt/myOrg/tomcat/webapps/MyApplication/lock.db] ma non è riuscito a fermarsi esso. Questo è molto probabile che crei una perdita di memoria. Media in catalina.out? Non l'ho creato, ma 'H2'. – Jim

risposta

4

Se l'applicazione Web viene arrestato, tutte le connessioni al database devono essere chiuse pure. Se non si dispone di un elenco di connessioni, eseguire l'istruzione SQL "shutdown" (funziona solo per i database H2 e HSQLDB).

Se si è un marchio registrato di una Servlet, si può fare nel metodo Servlet.destroy().

Se è stato registrato un ServletContextListener, è possibile eseguire l'istruzione "shutdown" nel metodo ServletContextListener.contextDestroyed(ServletContextEvent servletContextEvent). Questo è ciò che fa org.h2.server.web.DbStarterServletContextListener (quello incluso nel database H2).

+0

Grazie per la risposta! 'Se l'applicazione web viene interrotta, anche tutte le connessioni al database dovrebbero essere chiuse. Sto usando il pool di connessione di Tomcat. Quindi è fuori dalle mie mani. È un noto problema "da corsa" tra Tomcat e H2. Posso fare "ARRESTARE" (è sicuro, giusto?) Ma voglio essere sicuro di indirizzare correttamente questo problema. – Jim

+0

Vedere il problema. Non sei sicuro di quale sia la soluzione migliore ... ignori l'eccezione? L'istruzione 'SHUTDOWN' chiuderà solo questo database, quindi dovrebbe essere relativamente salvabile - solo se non sei sicuro che altre app web stiano utilizzando il database, non puoi farlo. Un'altra soluzione è utilizzare la modalità server (eseguire il database H2 in un altro processo). –

+0

: No il database è mio, cioè nessun'altra applicazione potrà accedervi. E sono obbligato ad usarlo in modalità file. Quindi in pratica stai dicendo che 1) l'arresto è sicuro per i dati 2) Posso ignorare l'eccezione che significa che cosa? Che Tomcat non si blocchi durante l'arresto a causa di H2 ancora in esecuzione? Vedo il file 'db.lock' nella directory della mia app – Jim

19

Scopri che le discussioni sono ancora in esecuzione (o bloccato, in attesa di esecuzione) utilizzando jstack o l'invio di un segnale al processo:

kill -3 pid 

Quando si sa questo, si può fare qualunque cosa fosse, li ha avviati alla notifica di arresto per interrompere i thread. Oppure fai quei fili con i fili di Deamon.

Vedere This tomcat shutdown question per maggiori dettagli su questo.

Se non si sa dove sono stati creati i thread, quindi prendere in considerazione l'aggiunta di nomi ad essi - gli executors possono prendere le fabbriche di thread, e si possono usare quelle fabbriche per impostare lo stato di deamon di un thread e anche per nominarlo - quindi la traccia dello stack sarà più chiara.

+0

+1. Vedere l'aggiornamento nell'OP – Jim

+0

Aprire il file javacore .txt in un editor di testo, cercare gli stack di thread che includono i pacchetti che hai scritto. – daveb

+0

Sì, l'ho capito. Ma non sono sicuro su cosa indichi un errore. – Jim

6

ho avuto lo stesso identico problema. A volte, il comando ./shutdown.sh non interrompe il processo di tomcat e il suo processo java rimane nei processi in esecuzione.

avevo risolto questo problema utilizzando la versione di Tomcat nel repository del Ubuntu, da:

sudo apt-get install tomcat7 

Dopo l'installazione dal gestore di pacchetti e la configurazione di alcune impostazioni, non ho avuto alcun problema a fermare/avviare Tomcat . Ho usato questo comando per arrestare, e non è mai venuto a mancare:

service tomcat7 stop 

che è quasi la stessa di

/etc/init.d/tomcat7 stop 

Utilizzando questo comando viene eseguito il blocco di codice dallo script di init, in particolare, i codici dalla file /etc/init.d/tomcat7. Così ho esaminato per vedere che cosa fa per uccidere sempre il processo di tomcat con successo. Ecco il blocco di codice che viene eseguito quando si utilizza service tomcat7 stop comando:

log_daemon_msg "Stopping $DESC" "$NAME" 

     set +e 
     if [ -f "$CATALINA_PID" ]; then 
       start-stop-daemon --stop --pidfile "$CATALINA_PID" \ 
         --user "$TOMCAT7_USER" \ 
         --retry=TERM/20/KILL/5 >/dev/null 
       if [ $? -eq 1 ]; then 
         log_progress_msg "$DESC is not running but pid file exists, cleaning up" 
       elif [ $? -eq 3 ]; then 
         PID="`cat $CATALINA_PID`" 
         log_failure_msg "Failed to stop $NAME (pid $PID)" 
         exit 1 
       fi 
       rm -f "$CATALINA_PID" 
       rm -rf "$JVM_TMP" 
     else 
       log_progress_msg "(not running)" 
     fi 
     log_end_msg 0 
     set -e 
     ;; 

La parte importante è questo:

start-stop-daemon --stop --pidfile "$CATALINA_PID" \ 
          --user "$TOMCAT7_USER" \ 
          --retry=TERM/20/KILL/5 >/dev/null 

Questo significa "riprovare l'arresto fino a quando si arresta il processo.Ecco la documentazione di comando --retry da start-stop-daemon manuale:

-R|--retry timeout|schedule 
      With --stop, specifies that start-stop-daemon is to check 
      whether the process(es) do finish. It will check repeatedly 
      whether any matching processes are running, until none are. If 
      the processes do not exit it will then take further action as 
      determined by the schedule. 

      If timeout is specified instead of schedule then the schedule 
      signal/timeout/KILL/timeout is used, where signal is the signal 
      specified with --signal. 
      ... 

Quindi, --retry=TERM/20/KILL/5 significa "Invia TERM segnale al processo, attendere 20 secondi, se è ancora esecuzione, inviare KILL segnale, attendere 5 secondi, se è ancora in esecuzione, c'è un problema.

questo significa che è possibile configurare il Tomcat per l'esecuzione come un demone e utilizzare un comando come questo, o scrivere uno script per fare quel tipo di azione per fermare Tomcat, o semplicemente usare Ubuntu e ottenere il tomcat dal gestore di pacchetti.

7

Verificare se l'applicazione Web dispone di un programma di pianificazione attivo, ad esempio Quarzo.

Se non fermarlo, Web Applicazione Filo senza fine fino a quando si uccide

1

Nel mio caso ho avuto una canaglia JPA EntityManager che non veniva chiuso correttamente dopo l'uso. Risolto il problema, e ora riesco a pulire e ricostruire di nuovo senza uccidere il maledetto processo Java ogni volta :)

0

Ho anche avuto lo stesso problema. C'era un ThrottledThreadPoolExecutor nella mia applicazione che non veniva arrestato. Quando lo spengo correttamente, tomcat si fermerebbe in modo pulito. Per capire il problema, ho dovuto rimuovere tutte le app dalla mia directory tomcat webapps e aggiungerle una alla volta e vedere quale causa causa il problema

0

Se si sta utilizzando un Pianificatore o qualche altra entità nella tua app Web, devi spegnerlo. In genere è necessario utilizzare un ServletContextListener per fornire l'hook per effettuare la chiamata di arresto. In questo caso, un hook di spegnimento non funzionerà perché la JVM non si sta arrestando (ancora). Credimi, ci ho provato. Se il tuo codice è in codice agente o qualcosa al di fuori del contenitore/webapp, allora un gancio di arresto DOVREBBE funzionare, anche se spesso è un capriccio per capire perché non funziona ancora. Nota, sono calvo.

Problemi correlati