Spring Scheduler意外停止

时间:2013-07-28 14:49:49

标签: java spring tomcat scheduled-tasks

我们在Tomcat 6上有一个Spring 3 Web应用程序,它通过@Scheduled使用多个计划服务(主要用于每晚运行的作业)。现在似乎有时(很少,也许在两个月左右)调度程序线程停止工作,因此在第二天晚上不会执行任何作业。我们的日志文件中没有异常或日志记录条目。

有人知道为什么会这样吗?或者如何获得有关此问题的更多信息?

有没有办法在应用程序中检测这种情况并重新启动调度程序?

目前,我们通过每5分钟运行一次日志记录作业并创建日志条目来解决此问题。如果日志文件停止更新(由nagios监视),我们知道是时候重启tomcat了。如果没有完整的服务器重启,重启作业会很不错。

3 个答案:

答案 0 :(得分:14)

由于这个问题获得了如此多的选票,我将发布我的问题的(可能是非常具体的)解决方案。

我们正在使用Apache HttpClient库来调用预定作业中的远程服务。不幸的是,执行请求时没有设置默认超时。设置后

connectTimeout
connectionRequestTimeout
socketTimeout
问题消失了30秒。

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 :(得分:3)

这很容易找到。您将使用堆栈跟踪执行此操作。有很多关于如何获得堆栈跟踪的帖子,在unix系统上你做'kill -3'并且堆栈跟踪出现在catalina.out日志文件中。

一旦有了堆栈跟踪,找到调度程序线程并查看它在做什么。它正在执行的任务是否可能卡住了?

您也可以在此处发布堆栈跟踪以获取更多帮助。

重要的是要知道您使用的调度程序。如果你使用SimpleAsyncTaskExecutor,它将为每个任务启动一个新线程,你的调度永远不会失败。但是,如果您的任务没有完成,最终会耗尽内存。

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

答案 2 :(得分:-1)

就我而言,堆栈跟踪是绝对干净的,线程仅启动了几次,仅此而已。问题出在另一个时间表上。

已更新

计划无法正常运行,因为我使用fixedDelayString并且以前的工作在开始新工作时没有结束。将时间表更改为fixedRateString后,线程将正确启动。