2013-07-28 19 views
26

Abbiamo un'applicazione web Spring 3 su Tomcat 6 che utilizza diversi servizi di pianificazione tramite @Scheduled (principalmente per i lavori che vengono eseguiti ogni notte). Ora sembra che a volte (raramente, forse una volta in due mesi o giù di lì) il thread dello scheduler smetta di funzionare, quindi nessuno dei lavori verrà eseguito nella notte seguente. Non ci sono eccezioni o voci di registrazione nei nostri file di registro.Spring Scheduler si arresta in modo imprevisto

Qualcuno ha idea del perché questo sta accadendo? O come ottenere maggiori informazioni su questo problema?

C'è un modo per rilevare questa situazione all'interno dell'applicazione e riavviare lo scheduler?

Attualmente stiamo risolvendo questo problema avendo anche un processo di registrazione che viene eseguito ogni 5 minuti e crea una voce di registro. Se il file di registro smette di essere aggiornato (monitorato da nagios), sappiamo che è il momento di riavviare Tomcat. Sarebbe bello riavviare i lavori senza un riavvio completo del server.

+6

Qual è il lavoro svolto nelle attività pianificate? È possibile che qualcosa si blocchi in un ciclo infinito? Chiedo perché le attività pianificate, per impostazione predefinita, utilizzano un threadpool di 1 thread e, se viene bloccato in qualche modo, le attività future non verranno avviate (ma sono sicuro che verranno accodate). –

+0

@ nicholas.hauschild Chiama un servizio web REST esterno. Quindi stai dicendo che una tale richiesta potrebbe eventualmente bloccare (deadlock?) E quindi interrompere tutti gli altri lavori. Penso che richiederò un dump del thread del server se questo dovesse accadere di nuovo. Grazie per il tuo contributo. – obecker

+0

Prendere una discarica di filo sarà probabilmente una buona idea. –

risposta

3

Questo è abbastanza facile da scoprire. Lo faresti con una traccia dello stack. Ci sono molti post su come ottenere una traccia dello stack, sul sistema unix si fa 'kill -3' e la traccia dello stack appare nel file di log catalina.out.

Una volta che si dispone di una traccia di stack, trovare il thread di pianificazione e vedere cosa sta facendo. È possibile che il compito che stava eseguendo sia rimasto bloccato?

Qui puoi anche inviare la traccia dello stack per ulteriore assistenza.

ciò che è importante sapere è quale scheduler si utilizza. se si utilizza SimpleAsyncTaskExecutor, verrà avviato un nuovo thread per ogni attività e la pianificazione non avrà esito negativo. Tuttavia, se si hanno compiti che non terminano, alla fine si esaurirà la memoria.

http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html

+0

Grazie - prendendo un dump del thread è già stato proposto da nicolas.hausschild e ho trovato una chiamata HTTP bloccata dal servizio REST. Ho aggiornato la libreria HttpClient e mi chiedo se questo potrebbe già risolvere il problema. – obecker

9

Dal momento che questa domanda ha ottenuto così tanti voti, vi posterò quale sia la soluzione (probabilmente molto specifico) al mio problema era.

Stiamo utilizzando la libreria Apache HttpClient per effettuare chiamate ai servizi remoti nei lavori pianificati. Sfortunatamente non ci sono scadenze predefinite impostate durante l'esecuzione delle richieste. Dopo aver impostato

connectTimeout 
connectionRequestTimeout 
socketTimeout 

a 30 secondi il problema era sparito.

int timeout = 30 * 1000; // 30 seconds 
RequestConfig requestConfig = RequestConfig.custom() 
     .setConnectTimeout(timeout) 
     .setConnectionRequestTimeout(timeout) 
     .setSocketTimeout(timeout).build(); 
HttpClient client = HttpClients.custom() 
     .setDefaultRequestConfig(requestConfig).build(); 
+1

Stavo affrontando lo stesso problema ESATTO con Apache HttpClient .... Tu, amico mio, sei un gentiluomo e uno studioso! – nterry

+0

Questo era davvero il mio problema, in particolare stava usando Jersey con ApacheConnector configurato con un PoolingHttpClientConnectionManager. È fondamentale impostare il parametro ** connectionRequestTimeout ** poiché il pool potrebbe bloccarsi indefinitamente se questo non è impostato. Per fare ciò, devi impostarlo in un RequestConfig e impostare l'intera configurazione di richiesta nella configurazione del client del connettore in questo modo: 'RequestConfig rc = RequestConfig.custom(). SetConnectTimeout (2000) .setSocketTimeout (2000) .setConnectionRequestTimeout (2000). 200) .build(); clientConfig.property (ApacheClientProperties.REQUEST_CONFIG, rc); ' – David

Problemi correlati