如果失败,Kotlin 重试计划的 cron 任务

Wil*_*oss 6 cron spring cron-task kotlin spring-boot

我下面有一个 Kotlin 调度配置文件。它有一项重要任务计划在每周一上午 11 点运行。

如果服务在上午 11 点停止,我需要做什么来建立弹性或重试?

这些 Spring Boot 和 Kotlin@Scheduled作业是否可以配置为企业级弹性,或者我是否需要使用 Kubernetes CronJobs 之类的东西来实现这一目标?

我还在研究带有 JobStore 作为选项的 Spring Boot Quartz 调度程序。欢迎任何替代设置建议。

@Component
class CronConfig {

    private val logger = LoggerFactory.getLogger(CronConfig::class.java)

    // Run Monday morning @ 11am
    @Scheduled(cron = "0 0 11 * * MON")
    fun doSomething(){
        logger.info("Doing something")
    }
}
Run Code Online (Sandbox Code Playgroud)

gid*_*dds 3

很好,您正在考虑可能会出现问题的地方。\xe2\x80\x82(我们开发人员经常假设一切都会顺利,并且不考虑和处理我们的代码可能失败的所有方式! )

\n

不幸的是,我认为这没有标准做法;正确的方法可能取决于您的具体情况。

\n

也许最简单的方法就是通过在其中进行错误处理以及如果需要的话等待和重试来确保您的函数不会失败。\xe2\x80\x82如果可以的话,您可以将实际处理拆分为单独的方法更具可读性,例如:

\n
@Scheduled(cron = "0 0 11 * * MON")\nfun doSomethingDriver() {\n    while (true) { // Keep trying until successful\xe2\x80\xa6\n        try {\n            doSomething()\n            return // It worked!\n        } catch (x: Exception) {\n            logger.error("Can\'t doSomething: {}.  Will retry\xe2\x80\xa6", x.message)\n            TimeUnit.SECONDS.sleep(10L)\n        }\n    }\n}\n\nfun doSomething() {\n    logger.info("Doing something")\n    // \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这非常简单。\xc2\xa0 一个缺点是它使线程在重试之间保持等待;由于 Spring 默认使用单线程调度程序(请参阅这些 问题),这意味着它可能会延迟任何其他计划的作业。

\n

或者,如果您的计划函数没有继续重试,那么您将需要其他方法来触发重试。

\n

您可以 \xe2\x80\x98poll\xe2\x80\x99:存储上次成功运行的时间,更改计划函数以更频繁地运行,并让它检查是否需要另一次运行(即是否有自周一上午 11 点以来没有成功运行)。\xe2\x80\x82这将更加复杂 \xe2\x80\x94 特别是因为它需要维护状态并进行日期/时间处理。\xe2\x80\x82(您应该不过,不需要担心并发性,除非您已经创建了该函数@Async或设置了自己的调度配置。)\xe2\x80\x82由于所有额外的计划唤醒,它的效率也有点低-UPS。

\n

或者您可以捕获错误(如上面的代码),但不是等待和重试,而是手动安排将来的重试,例如使用您自己的TaskExecutor。\xe2\x80\x82 这也会更复杂。

\n