【问题标题】:Making @Schedule run only once in a clustered environment使@Schedule 在集群环境中只运行一次
【发布时间】:2014-10-16 10:58:21
【问题描述】:

我有两个集群的 tomee 实例。

每个方法都有一个类似注释的方法

@Schedule(dayOfWeek = "*")
public void runMeDaily() {...}

我希望每天只运行一次此方法。不是一天两次(每个实例一次)

我可以使用此处描述的标志Run @Scheduled task only on one WebLogic cluster node? 或者只是选择一些节点,但我想知道是否有更优雅的方法来做到这一点。

这个问题与EJB3.1 @Schedule in clustered environment有些关系,但我没有使用JBOSS。 (并且没有回答)

【问题讨论】:

标签: java jakarta-ee quartz-scheduler apache-tomee


【解决方案1】:

我使用与其他线程相同的方法 - 检查特定主机是否是运行作业的正确主机。但是..

我不是很了解信息的工具,但在春天你可以使用配置文件。可能您可以找到满足您需求的类似解决方案。看看http://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles

您可以定义两个单独的 bean:

@Configuration
@Profile("dev")
public class StandaloneDataConfig {

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("classpath:com/bank/config/sql/schema.sql")
        .addScript("classpath:com/bank/config/sql/test-data.sql")
        .build();
}
}

@Configuration
@Profile("production")
public class JndiDataConfig {

@Bean
public DataSource dataSource() throws Exception {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}

并通过切换配置文件来决定打开哪一个。因此,您的带有 @Scheduled 方法注释的类将仅针对特定配置文件加载。当然,您需要将您的应用程序配置为仅打开节点的配置文件。在 spring 应用程序中,它就像将 -Dspring.profiles.active=profile 传递给其中之一一样简单。

【讨论】:

  • 好主意,我去看看 :-) 恐怕我现在不能在这个项目中切换到 spring,但我肯定会在下一个项目中考虑你的选择.谢谢!
  • 就像我说的,你可能在 ejb 中可以找到类似的东西。
【解决方案2】:

我只能使用特定于平台(专有)的非 Java EE 解决方案来解决这个问题。就我而言,我使用的是 TomEE+ 和 Quartz。以集群模式运行 Quartz (org.quartz.jobStore.isClustered = true) 并将定时器持久化在单个数据库中会强制 Quartz 选择一个实例来触发定时器,因此它只会运行一次。

这个链接非常有用——http://rmannibucau.wordpress.com/2012/08/22/tomee-quartz-configuration-for-scheduled-methods/

很遗憾,Java EE 没有为此指定行为。 (但是,我希望):-)

【讨论】:

    【解决方案3】:

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

    并通过 system.getenv("master") 在您的 java 代码中读取它。如果它存在并且它是真的,那么运行你的代码。

    基本sn-p

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

    【讨论】:

      猜你喜欢
      • 2018-03-31
      • 1970-01-01
      • 2018-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多