当前位置: 首页 > 知识库问答 >
问题:

跨多个实例只运行一次调度作业

甘兴学
2023-03-14

我有一个计划作业,每个月底运行一次。运行后,它会将一些数据保存到数据库中。

当我扩展应用程序时(例如有2个实例),两个实例都运行计划作业,并且都保存数据,在一天结束时,我的数据库有相同的数据。

所以我希望计划作业只运行一次,而不管云上的实例数量如何。

共有3个答案

汝才良
2023-03-14

您可以在方法中使用@SnapLock注释,以保证任务只运行一次。请参阅此存储库中的留档https://github.com/luismpcosta/snap-scheduler

示例:导入maven依赖项

<dependency>
  <groupId>io.opensw.scheduler</groupId>
  <artifactId>snap-scheduler-core</artifactId>
  <version>0.3.0</version>
</dependency>

导入 maven 依赖项后,需要创建所需的表表。

最后,请参阅下面如何注释使用@SnapLock注释保证只运行一次的方法:

import io.opensw.scheduler.core.annotations.SnapLock;
...

  @SnapLock(key = "UNIQUE_TASK_KEY", time = 60)
  @Scheduled(fixedRate = 30000)
  public void reportCurrentTime() {
    ...
  }

使用这种方法,您还可以保证任务执行的审计。

宗政燕七
2023-03-14

我同意这些评论。如果你能利用一个调度器,那将是你最好的、最灵活的选择。此外,一个调度程序应该在Cloud Foundry上作为一个“任务”来执行您的工作。该任务将只在一个实例上运行,所以您不需要担心您的应用程序使用了多少个实例(这两个实例是分开的)。

如果您使用的是 Pivotal Cloud Foundry/Tanzu Cloud Foundry,您可以要求运营团队安装一个调度程序。我不知道 CF 的其他变体,但我认为还有其他调度程序。

https://network.pivotal.io/products/p-scheduler/

如果使用调度器不是一个选项,那么这是您需要在应用程序中处理的问题。使用共享锁的解决方案是一个很好的解决方案,但在Cloud Foundry上还有一个小技巧,我觉得它简单了一点。

当您的应用程序运行时,某些环境变量由平台设置。有一个名为INSTANCE_INDEX的应用程序有一个数字,指示运行应用程序的实例。它是从零开始的,因此您的第一个应用程序实例将在实例零上运行,第二个实例将在实例一上运行,等等。

在您的代码中,只需查看实例索引,看看它是否为零。如果索引不为零,则让您的任务在不做任何事情的情况下结束。如果为零,则让任务继续并完成其工作。该任务将在每个应用程序实例上执行,但它只会在第一个实例上执行工作。这是一种简单的方法,可以保证数据库迁移或后台作业只运行一次。

最后一个选择是使用多个进程。这是Cloud Foundry的一项功能,使您能够运行不同的进程,例如您的Web进程和后台工作进程。

https://docs.cloudfoundry.org/devguide/multiple-processes.html

此功能的有趣之处在于,您可以彼此独立地扩展不同的进程。因此,您可以运行尽可能多的 Web 进程,但只有一个后台工作线程,这将保证您的后台进程只运行一次。

也就是说,这种方法的缺点是每个进程都有单独的容器,并且后台进程需要继续运行。基金会希望这是一个长期运行的过程,而不是一个有限持续时间的批处理作业。你可以通过把你的周期性任务包装成一个循环或者其他什么东西来让这个过程永远运行,从而解决这个问题。

我不会真的推荐这个选项,但我想把它扔在那里以防万一。

孔正文
2023-03-14

在我的项目中,我维护了一个数据库表,为集群中只需要执行一次的每个作业保存一个锁。当一个作业被触发时,它首先尝试从数据库中获取锁,如果它只获得该锁,那么它将被执行。如果它未能获得锁,那么作业将不会被执行。

您还可以查看Quartz作业的群集特性。

http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/introduction.html

 类似资料:
  • 是否可以只在指定的时间安排一次Spring服务方法?例如,当前时间是下午2点,但当我点击action按钮时,我希望我的服务方法在晚上8点开始。我很熟悉@Schedured注释,我不确定如何编写不定期运行的cron表达式。这个每天晚上8点触发。 有什么建议吗?

  • 我试图在Quartz 1.6中创建一个,但必须只执行一次,因为我有两个测试实例具有相同版本的.war文件。 这是我的类,将每60秒执行一次: 然后我有我的类来打印一个简单的输出:

  • 问题内容: 我需要防止用户多次启动我的Java应用程序(WebStart Swing应用程序)。因此,如果应用程序已经在运行,则应该无法再次启动它或显示警告/再次关闭它。 有一些方便的方法可以做到这一点吗?我考虑过要阻止端口或将某物写入文件。但是希望您可以访问某些系统属性或JVM? 顺便说一句 目标平台是带有Java 1.5的Windows XP 问题答案: 我认为您的建议是在启动应用程序时打开端

  • 我已经创建了Spring Batch(RESTReader、自定义处理器和自定义ItemWriter),我计划了它。Spring批工作良好。当监听器在每个计划的间隔内完成打印作业时,计划似乎可以工作,但似乎不读或写。 我的Sprint启动应用程序 BATCH_STEP_EXECUTION 控制台日志的一部分 BatchApplication-在27.638秒内启动BatchApplication(

  • 我希望一个进程在我启动我的网络服务后运行,然后每隔30分钟左右运行一次(我现在用较小的延迟测试它,只是为了看看它是否工作),但是我的进程从来不会运行超过一次。我做错了什么? 这是我的密码:

  • 问题内容: 有没有一种Python方式可以只运行一个程序实例? 我想出的唯一合理的解决方案是尝试将其作为服务器在某个端口上运行,然后尝试将第二个程序绑定到同一端口-失败。但这不是一个好主意,也许有比这更轻巧的东西了吗? (考虑到程序有时可能会失败,例如segfault-因此“锁定文件”之类的东西将无法工作) 问题答案: 以下代码可以完成此工作,它是跨平台的,并且可以在Python 2.4-3.2上