58

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

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

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

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

4

3 回答 3

23

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

我们正在使用 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();
于 2015-04-14T10:01:59.310 回答
4

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

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

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

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

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

于 2014-02-10T20:29:50.107 回答
0

在我的情况下,堆栈跟踪绝对干净,线程只启动了几次,仅此而已。该问题与另一个时间表相冲突。

更新

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

于 2019-12-02T21:31:03.613 回答