2014-10-16 2 views
5

У меня есть два экземпляра tomee, сгруппированные.Выполнение @ Расписание запускается только один раз в кластерной среде

Каждый имеет метод аннотированный как

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

я хотел бы запустить этот метод только один раз в день. Не два раза в день (по одному на каждом экземпляре)

Я мог бы использовать флаг, как описано здесь Run @Scheduled task only on one WebLogic cluster node?, или просто выбрать какой-либо узел, но мне интересно, есть ли более элегантный способ сделать это.

Этот вопрос несколько связан с EJB3.1 @Schedule in clustered environment, но я не использую JBOSS. (и он не ответил)

+0

https://github.com/SpringOnePlatform2016/dsyer-locks-and-leaders – MariuszS

ответ

1

Я мог бы решить только это использование не-Java EE решения, специфичные для платформы (собственный). В моем случае я использую TomEE + и Quartz. Запуск кварца в кластерном режиме (org.quartz.jobStore.isClustered = true) и сохранение таймеров в одной базе данных заставляет Quartz выбирать экземпляр для запуска таймера, поэтому он будет запускаться только один раз.

Эта ссылка была очень полезной - http://rmannibucau.wordpress.com/2012/08/22/tomee-quartz-configuration-for-scheduled-methods/

Это позор Java EE не определяет поведение для этого. (все же, я надеюсь) :-)

2

Я использую тот же подход, что и в другом потоке - проверка того, что конкретный хост является правильным для запуска задания. Но ..

Im не очень информация ee инструменты, но весной вы можете использовать профили для этого. Вероятно, вы можете найти подобное решение для своих нужд. Посмотрите на http://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles

Вы можете определить два отдельных зерен:

@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 будет загружен только для определенного профиля. Конечно, вам нужно настроить приложение, чтобы включить профиль только из узлов. В весеннем приложении это будет так же просто, как передать -Dspring.profiles.active = profile в один из них.

+0

отличная идея, я посмотрю на это :-) Боюсь, t переключитесь на весну в этом проекте прямо сейчас, но я обязательно рассмотрю ваш вариант в следующем. спасибо! – Leo

+0

Как я уже сказал, вы, вероятно, найдете что-то подобное в ejb. – freakman

-1

Я решил эту проблему, сделав одно из ящиков мастером. в основном устанавливают переменную среды на одном из полей, например master = true.

и прочитайте его в своем java-коде через system.getenv («master»). если его настоящее и его истинное, тогда запустите свой код.

основной фрагмент

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

} 
Смежные вопросы