仅在一个服务器实例上激活 Batch

Activate Batch on only one Server instance

我在两个 tomcat 实例前面有一个 nginx 负载均衡器,每个实例都包含一个 spring 启动应用程序。每个 spring 引导应用程序执行一个将数据写入数据库的批处理。 该批处理每天凌晨 1 点执行。 问题是两个实例同时执行我不想要的批处理。

有没有办法让批处理部署在两个实例中并告诉 tomcat 或 nginx 在主服务器中启动批处理(而从属服务器不 运行 批处理)。

如果其中一台服务器停止,第二台服务器可以代表他启动批处理。

nginx 或 tomcat(或其他技术)中是否有工具可以做到这一点?

提前致谢。

这是一个简单的设计方法。

由于您在 2 个 VM 中同时触发了两个计划方法,因此请为两者添加一个随机延迟。这个答案有很多关于如何将触发器延迟随机持续时间的选项。

在方法 运行 中,仅当作业尚未启动时(由其他 VM)。这可以通过一个新的 table 来跟踪。

这里是这个设计的伪代码:

@Scheduled(cron = "schedule expression")
public void batchUpdateMethod() {
     //Check database for signs of job running now.
     if (job is not running){
         //update database table to indicate job is running
         //Run the batch job
         //update database table to indicate job is finished
     }
}

数据库或一些公共文件位置应该用作两个 运行 之间同步的锁,因为两个 VM 彼此独立。

要获得更稳健的设计,请考虑 Spring 批处理 Spring Batch 为其作业使用数据库 (JobsRepository)。默认情况下,内存数据源用于跟踪 运行ning 作业及其状态。在您的设置中,这 2 个实例(很可能)使用它们自己的内存数据库。 Spring Batch 的多个实例可以作为一个集群相互协调,一个可以 运行 作业,而另一个作为备份,如果 jobsRepository 数据库是共享的。 为此,您需要将 2 个实例配置为使用公共数据源。

以下是一些文档: https://docs.spring.io/spring-batch/docs/current/reference/html/index-single.html#jobrepository

https://docs.spring.io/spring-batch/docs/current/reference/html/job.html#configuringJobRepository

如果你设计两个应用服务器实例同时运行同一个作业,那么根据设计,一个会成功创建一个作业实例,另一个会失败(这个失败可以忽略).参见 Javadoc of JobRepository。这是作业存储库的作用之一:在集群环境中充当防止重复作业执行的保护措施。

If one of the servers stops, the second server could start the batch on his behalf. Is there a tool in nginx or tomcat (or some other technology) to do that ?

我认为不需要这样的工具或技术。如果其中一台服务器在计划时间停机,另一台将能够接管并成功启动作业。

我确实实现了一个简单的 BCM 服务器功能,其中所有服务器都使用其唯一 IP 注册(创建一个 Server-table 条目)。服务器需要在定义的时间内注册(例如 10 秒)。如果服务器未在时间内注册(上次更新时间戳 > 10 秒),则服务器将被注册的服务器取消注册(删除服务器-table 条目)。

最后,我确实有一个 table,其中包含有序的服务器条目,并且可以为已注册的服务器定义唯一的任务。

实施非常简单,而且工作完美。 之前我也想到了 Spring Batch Job Sharing 功能,但我希望 zu 有一个更轻量级和更灵活的解决方案。

目前,我在所有需要实施批处理的项目中都使用它。