多个实例上的Spring和计划任务

Com*_*mbo 2 jobs spring job-scheduling spring-boot

我们有一个Spring Boot应用程序,并有计划的任务。

我们希望将应用程序部署在多台服务器上,因此将有多个应用程序实例。

如何配置Spring以仅在指定的服务器上运行计划的任务?

Ami*_*ane 11

春天- ShedLock项目专门创建实现这一目标。

依赖 -

<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>    
Run Code Online (Sandbox Code Playgroud)

配置 -

@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
Run Code Online (Sandbox Code Playgroud)

执行 -

@Scheduled(cron = "0 0/15 * * * ?")
@SchedulerLock(name = "AnyUniqueName", 
  lockAtLeastForString = "PT5M", lockAtMostForString = "PT10M")
public void scheduledTask() {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

此设置将确保只有一个实例应该运行计划任务。

如果你只想要一个特定的实例应该运行 Scheduler 任务,

您需要配置调度程序以使用属性文件并像这样控制调度程序开关 -

@ConditionalOnProperty(
  value = "scheduling.enabled", havingValue = "true", matchIfMissing = true
)
@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "PT30S")
public class SchedulingConfig {
Run Code Online (Sandbox Code Playgroud)

现在,您需要scheduling.enabled = trueapplication.properties文件中为您希望运行 Schedular 的实例提供一个属性。


pvp*_*ran 10

这是一个非常广泛的话题。有很多选择可以实现这一目标。

  1. 您可以将应用程序配置为具有多个配置文件。例如,使用另一个配置文件“ cron”。并仅使用此配置文件在一台服务器上启动您的应用程序。因此,例如,在生产环境中,您具有三台服务器(S1,S2,S3),那么您可以在S1上使用概要文件prod和cron(-Dspring.profiles.active=prod,cron)运行。在S2和S3上,只需使用prod profile(-Dspring.profiles.active=prod)。

    在代码中,您可以@Profile("cron")在调度程序类上使用。这样,仅当cron配置文件处于活动状态时才执行

  2. 使用分布式锁。如果您的环境中有Zookeeper,则可以使用它来实现分布式锁定系统。

  3. 您可以使用一些数据库(mysql)并创建示例代码来获取对其中一个表的锁定并添加一个条目。无论哪个实例获得了锁,都将在该数据库中创建一个条目并执行cron作业。您需要在代码中进行检查,如果getLock()只有成功,则继续执行。Mysql具有类似的实用程序LOCK TABLES,您可以使用它们来避免并发读/写。

我个人会说,选择2是最好的。


Ale*_*nov 6

最好的选择之一 - 使用带有集群的 Quartz 调度程序。很简单,只需:

implementation("org.springframework.boot:spring-boot-starter-quartz")
Run Code Online (Sandbox Code Playgroud)

并使用 spring 配置quartz 的作业(参见教程

application.yaml 中的集群配置:

implementation("org.springframework.boot:spring-boot-starter-quartz")
Run Code Online (Sandbox Code Playgroud)

注意initialize-schema: never- 集群模式需要自行初始化

查看官方脚本:https://github.com/quartz-scheduler/quartz/tree/master/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore
并且可以通过liquibase/flyway/etc使用它,但删除DROP ...查询!这就是为什么在集群中我们不自动初始化模式。

请参阅quartz 文档
请参阅spring boot 文档quartz
请参阅带有示例的文章