使@Schedule仅在群集环境中运行一次

时间:2014-10-16 10:58:22

标签: java java-ee quartz-scheduler tomee

我有两个tomee实例聚集。

每个人都有一个注释方法,如

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

我想每天只运行一次这种方法。一天不是两次(每个实例一次)

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

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

3 个答案:

答案 0 :(得分:2)

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

我不是非常有用的工具,但在春天你可以使用配置文件。您可以找到适合您需求的类似解决方案。看看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传递给其中一个一样简单。

答案 1 :(得分:1)

我只能使用特定于平台(专有)的非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没有为此指定行为。 (但我希望): - )

答案 2 :(得分:-1)

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

并通过system.getenv(“master”)在java代码中读取它。如果它的存在及其真实然后运行你的代码。

基本代码段

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

}