Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 是否仅在一个WebLogic群集节点上运行@Scheduled task?_Spring_Weblogic_Scheduled Tasks_Cluster Computing - Fatal编程技术网

Spring 是否仅在一个WebLogic群集节点上运行@Scheduled task?

Spring 是否仅在一个WebLogic群集节点上运行@Scheduled task?,spring,weblogic,scheduled-tasks,cluster-computing,Spring,Weblogic,Scheduled Tasks,Cluster Computing,我们正在集群WebLogic 10.3.4环境中运行一个Spring 3.0.x web应用程序(.war),该应用程序具有夜间@Scheduled作业。但是,当应用程序部署到每个节点时(使用AdminServer的web控制台中的部署向导),作业每晚都会在每个节点上启动,因此会并发运行多次 我们如何防止这种情况发生? 我知道像Quartz这样的库允许通过数据库锁表在集群环境中协调作业,或者我甚至可以自己实现类似的功能。但是,由于这似乎是一个相当常见的场景,我想知道Spring是否还没有提供一个

我们正在集群WebLogic 10.3.4环境中运行一个Spring 3.0.x web应用程序(.war),该应用程序具有夜间@Scheduled作业。但是,当应用程序部署到每个节点时(使用AdminServer的web控制台中的部署向导),作业每晚都会在每个节点上启动,因此会并发运行多次

我们如何防止这种情况发生?

我知道像Quartz这样的库允许通过数据库锁表在集群环境中协调作业,或者我甚至可以自己实现类似的功能。但是,由于这似乎是一个相当常见的场景,我想知道Spring是否还没有提供一个选项,如何在不向我的项目中添加新库或手动解决方法的情况下轻松绕过这个问题

  • 我们无法使用配置文件升级到Spring 3.1

如果有任何悬而未决的问题,请告诉我。我也在网上问了这个问题。非常感谢您的帮助。

我们正在使用应用程序数据库中的共享锁表实现我们自己的同步逻辑。这允许所有群集节点在实际启动作业之前检查作业是否已在运行。

我们只有一个任务发送每日摘要电子邮件。为了避免额外的依赖关系,我们只需检查每个节点的主机名是否与配置的系统属性相对应

private boolean isTriggerNode() {
   String triggerHostmame = System.getProperty("trigger.hostname");;
   String hostName = InetAddress.getLocalHost().getHostName();
   return hostName.equals(triggerHostmame);
}

public void execute() {
   if (isTriggerNode()) {
      //send email
   }
}

请小心,因为在使用共享锁表实现您自己的同步逻辑的解决方案中,两个集群节点同时从表中读取/写入数据时,始终存在并发问题

最好是在一个db事务中执行以下步骤: -读取共享锁表中的值 -如果没有其他节点具有该锁,则获取该锁
-更新表,指示您获得锁

您可以尝试使用WebLogic中的TimerManager(群集环境中的作业调度器)作为TaskScheduler实现(TimerManager TaskScheduler)。它应该在集群环境中工作


安德里亚

我解决了这个问题,让其中一个盒子成为主人。 基本上在其中一个框上设置一个环境变量,如master=true

并通过system.getenv(“master”)在java代码中读取它。 如果它存在且为真,则运行代码

基本片段

@schedule()
void process(){
boolean master=Boolean.parseBoolean(system.getenv("master"));
if(master)
{
   //your logic
}

}

我们可以使用以下cron字符串使集群上的其他机器不运行批处理作业。它要到2099年才会运行


01??2099

我最近实现了一个简单的注释库,只在多个节点上执行一次计划任务。您可以简单地执行以下操作

@Scheduled(cron = "59 59 8 * * *" /* Every day at 8:59:59am */)
@TryLock(name = "emailLock", owner = NODE_NAME, lockFor = TEN_MINUTE)
public void sendEmails() {
  List<Email> emails = emailDAO.getEmails();
  emails.forEach(email -> sendEmail(email));
}
@计划(cron=“59 59 8***”/*每天上午8:59:59*/)
@TryLock(name=“emailLock”,owner=NODE\u name,lockFor=十分钟)
公众电邮(电邮){
List emails=emailDAO.getEmails();
emails.forEach(email->sendmail(email));
}

有关使用它的信息,请参阅我的。

您不需要使用数据库同步作业。 在weblogic应用程序上,您可以获取应用程序正在运行的实例名称:

String serverName = System.getProperty("weblogic.Name");
只需将执行作业的条件设置为2:

if (serverName.equals(".....")) {
  execute my job;
}
如果你想将你的工作从一台机器跳转到另一台机器,你可以得到一年中的当前日期,如果你在一台机器上执行任务是奇怪的,如果是偶数,你可以在另一台机器上执行任务。
这样,您可以每天加载不同的计算机。

是否要实现某种故障切换?如果是这样的话,配置文件在这里就没有什么帮助了,而且您仍然需要一些同步。我们有一个类似的要求,最后得到了一个锁表,它还提供了一些快速执行摘要。@mrembisz不,我们(目前)没有寻找故障转移,因为这会使事情变得非常复杂。嗨,Mathias。尽管已经有一段时间了,谢谢你的建议。我们实际上在单个事务中检查和写入锁条目。好的观点和一个常见的陷阱。你在这里使用的隔离级别是什么?Read_committed或serializable?我认为这不是最好的解决方案,让我们假设您有一个由两个节点组成的集群,您将第一个节点作为主节点,而第二个节点不是。在此之后,由于任何原因,第一个节点关闭,那么您的作业将不会执行,因为应该处理作业的节点关闭,因此您将失去群集环境中最重要的功能“高可用性”