弹簧调度程序意外停止

2022-08-31 16:29:07

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

有没有人知道为什么会发生这种情况?或者如何获取有关此问题的更多信息?

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

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


答案 1

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

我们正在使用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();

答案 2

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

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

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

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

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


推荐