Spring 启动 - 运行 计划的作业作为单独的进程

Spring Boot - running scheduled jobs as separate process

我有一个 spring 启动应用程序,它也有很少的计划作业。我没有看到任何与实施有关的功能问题。其中一项工作几乎每秒钟运行一次以进行实时更新。还有其他工作。

我怀疑存在性能问题,尤其是当长 运行 API 命中控制器时。

// Heavy Job
@Scheduled(fixedRate = 10000)
public void processAlerts(){
}


@Scheduled(fixedDelayString = "${process.events.interval}")
public void triggerTaskReadiness() throws IOException {
    log.info("Trigger event processing job");
}
// Heavy Job to process data from different tables.
@Scheduled(fixedDelayString = "${app.status.interval}")
public void triggerUpdateAppHealth() throws IOException {
    log.info("Trigger application health");
}

是否可以将作业作为单独的进程。让 spring 启动繁重作业的应用程序的最佳做法是什么。

这个问题太笼统了,IMO。这完全取决于您的资源以及工作的具体内容。

Spring boot 提供了一种通用的调度机制,但不对作业性质做出任何假设。

总而言之,当您 运行 一份繁重的工作、CPU、网络、I/O 以及消耗的任何资源时(同样,取决于实际你的工作代码)。

如果你 运行 它在外部基本上另一个进程将消耗相同的资源假设它是 运行 在同一台服务器上。

从 spring 启动的角度来看,我可以说如下:

  1. 看来是处理数据库的工作。在这种情况下 Spring 引导支持与 DataSources、连接池、事务管理、更多高级 API 像 JPA 甚至 spring 数据的集成,你也可以插入像 JOOQ 这样的框架。最重要的是,它使数据库的实际工作变得更加容易。

您在问题标签中陈述了 Mongodb - 那么,spring 也在 spring 数据中集成了 mongo 数据库。

最重要的是,如果您 运行 在外部流程中完成工作,那您就只能靠自己了(这并不意味着无法完成,只是意味着您失去了所有好东西 spring 袖手旁观)

  1. AppHealth - spring boot 已经提供了一个具有数据库健康端点的执行器功能,它还提供了一种创建自己的端点以检查任何具体资源的健康状况的方法(你在代码中实现它,所以你可以自由地检查你想要的)。确保您使用正确的工具来完成正确的工作。

  2. 关于控制器API。如果你是运行传统的springmvc,tomcat有一个线程池来服务API,所以从线程管理的角度来看job的线程不会与控制器的线程竞争,但它们可能会共享相同的数据库连接,因此它可能成为瓶颈。

  3. 关于@Scheduled的实施。默认情况下,将有一个线程来处理所有 @Scheduled 个作业,这可能不够用。

您可以通过创建自己的 taskScheduler:

来改变此行为
@Bean(destroyMethod = "shutdown")
public Executor taskScheduler() {
    return Executors.newScheduledThreadPool(10); // allocate 10 threads to run @Scheduled jobs
}

您可能有兴趣阅读 this discussion

  1. Spring @Scheduled 总是工作 "within the boundaries" 一个 spring 托管应用程序上下文。因此,如果您决定扩展您的实例,每个实例都将 运行 "scheduled" 代码并执行繁重的工作。 可以将 Quartz 与 spring can be integrated 一起用于集群模式,您可以将其配置为每次选择一个节点并执行作业,但由于您计划每秒 运行 ,我怀疑石英是否足够好。

  2. 一般观察:运行如您所说的一组 "heavy" 工作与 "running every second" 听起来不太相符。这听起来不合理,因为繁重的工作往往持续时间比 1 秒长得多,所以这样做最终会占用所有资源,你将无法 运行 更多工作。