Run @Scheduled task only on one WebLogic cluster n

2019-03-25 03:53发布

We are running a Spring 3.0.x web application (.war) with a nightly @Scheduled job in a clustered WebLogic 10.3.4 environment. However, as the application is deployed to each node (using the deployment wizard in the AdminServer's web console), the job is started on each node every night thus running multiple times concurrently.

How can we prevent this from happening?

I know that libraries like Quartz allow coordinating jobs inside clustered environment by means of a database lock table or I could even implement something like this myself. But since this seems to be a fairly common scenario I wonder if Spring does not already come with an option how to easily circumvent this problem without having to add new libraries to my project or putting in manual workarounds.

  • We are not able to upgrade to Spring 3.1 with configuration profiles, as mentioned here

Please let me know if there are any open questions. I also asked this question on the Spring Community forums. Thanks a lot for your help.

8条回答
萌系小妹纸
2楼-- · 2019-03-25 04:12

We only have one task that send a daily summary email. To avoid extra dependencies, we simply check whether the hostname of each node corresponds with a configured system property.

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
   }
}
查看更多
对你真心纯属浪费
3楼-- · 2019-03-25 04:13

I've recently implemented a simple annotation library, dlock, to execute a scheduled task only once over multiple nodes. You can simply do something like below.

@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));
}

See my blog post about using it.

查看更多
▲ chillily
4楼-- · 2019-03-25 04:22

you can try using TimerManager (Job Scheduler in a clustered environment) from WebLogic as TaskScheduler implementation (TimerManagerTaskScheduler). It should work in a clustered environment.

Andrea

查看更多
你好瞎i
5楼-- · 2019-03-25 04:23

We are implementing our own synchronization logic using a shared lock table inside the application database. This allows all cluster nodes to check if a job is already running before actually starting it itself.

查看更多
Summer. ? 凉城
6楼-- · 2019-03-25 04:26

We can make other machines on cluster not run the batch job by using the following cron string. It will not run till 2099.

0 0 0 1 1 ? 2099

查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-03-25 04:33

I solved this problem by making one of the box as master. basically set an environment variable on one of the box like master=true.

and read it in your java code through system.getenv("master"). if its present and its true then run your code.

basic snippet

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

}
查看更多
登录 后发表回答