Nous avons une application Web Spring 3 sur Tomcat 6 qui utilise plusieurs services planifiés via @Scheduled
(principalement pour les travaux qui s'exécutent tous les soirs). Maintenant, il semble que parfois (rarement, peut-être une fois tous les deux mois environ) le thread du planificateur cesse de fonctionner, donc aucun des travaux ne sera exécuté la nuit suivante. Il n'y a aucune exception ou entrée de journalisation dans nos fichiers journaux.
Quelqu'un at-il une idée de pourquoi cela se produit? Ou comment obtenir plus d'informations sur ce problème?
Existe-t-il un moyen de détecter cette situation dans l'application et de redémarrer le planificateur?
Actuellement, nous résolvons cela en ayant également un travail de journalisation qui s'exécute toutes les 5 minutes et crée une entrée de journal. Si le fichier journal cesse d'être mis à jour (surveillé par nagios), nous savons qu'il est temps de redémarrer Tomcat. Ce serait bien de redémarrer les travaux sans redémarrage complet du serveur.
Étant donné que cette question a obtenu autant de votes, je publierai quelle était la solution (probablement très spécifique) à mon problème.
Nous utilisons la bibliothèque Apache HttpClient pour appeler des services distants dans les travaux planifiés. Malheureusement, aucun délai d'expiration par défaut n'est défini lors de l'exécution des demandes. Après le réglage
connectTimeout
connectionRequestTimeout
socketTimeout
à 30 secondes le problème avait disparu.
int timeout = 30 * 1000; // 30 seconds
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(timeout)
.setConnectionRequestTimeout(timeout)
.setSocketTimeout(timeout).build();
HttpClient client = HttpClients.custom()
.setDefaultRequestConfig(requestConfig).build();
C'est assez facile à découvrir. Vous feriez cela avec une trace de pile. Il existe de nombreux articles sur la façon d'obtenir une trace de pile, sur le système Unix vous faites 'kill -3' et la trace de pile apparaît dans le fichier journal catalina.out.
Une fois que vous avez une trace de pile, recherchez le thread du planificateur et voyez ce qu'il fait. Est-il possible que la tâche qu'il exécutait soit bloquée?
vous pouvez également publier la trace de la pile ici pour plus d'aide.
ce qui est important de savoir, c'est quel planificateur vous utilisez. si vous utilisez SimpleAsyncTaskExecutor, il lancera un nouveau thread pour chaque tâche et votre planification n'échouera jamais. Toutefois, si vous avez des tâches qui ne se terminent pas, vous finirez par manquer de mémoire.
http://docs.spring.io/spring/docs/3.0.x/reference/scheduling.html
Dans mon cas, la trace de la pile était absolument propre, le thread n'a démarré que quelques fois et c'est tout. Le problème était en conflit avec un autre calendrier.
mis à jour
Le calendrier ne fonctionne pas correctement, car j'utilise fixedDelayString
et le travail précédent n'est pas terminé quand était temps de commencer nouveau. Après avoir modifié la planification en fixedRateString
, les threads ont démarré correctement.