8

我不太确定这更多的是 Openbravo 问题还是 Quartz 问题,但我们有一些手动进程通过 OpenbravoProcessRequest对象(OB v2.50MP24)按计划运行,但似乎这些进程运行了两次,同时。Openbravo 为他们的调度扩展了 Quartz 平台。我试图通过确保我的流程类扩展此类来自行解决此问题:

import java.util.List;

import org.openbravo.dal.service.OBDal;
import org.openbravo.model.ad.ui.ProcessRequest;
import org.openbravo.scheduling.ProcessBundle;
import org.openbravo.service.db.DalBaseProcess;

public abstract class RBDDalProcess extends DalBaseProcess {

    @Override
    protected void doExecute(ProcessBundle bundle) throws Exception {
        org.quartz.Scheduler sched = org.openbravo.scheduling.OBScheduler
                .getInstance().getScheduler();
        int runCount = 0;
        synchronized (sched) {
            List<org.quartz.JobExecutionContext> currentlyExecutingJobs = (List<org.quartz.JobExecutionContext>) sched
                    .getCurrentlyExecutingJobs();
            for (org.quartz.JobExecutionContext jec : currentlyExecutingJobs) {
                ProcessRequest processRequest = OBDal.getInstance().get(
                        ProcessRequest.class, jec.getJobDetail().getName());
                if (processRequest == null)
                    continue;
                String processClass = processRequest.getProcess()
                        .getJavaClassName();
                if (bundle.getProcessClass().getCanonicalName()
                        .equals(processClass)) {
                    runCount++;
                }
            }
        }

        if (runCount > 1) {
            System.out.println("Process "
                    + bundle.getProcessClass().getSimpleName()
                    + " is already running. Cancelling.");
            return;
        }

        doRun(bundle);
    }

    protected abstract void doRun(ProcessBundle bundle);

}

当我通过请求该进程同时立即运行两次来进行测试时,这工作得很好。其中之一取消了。但是,它不适用于预定的流程。我将 Sop 设置为在进程启动时记录日志,查看日志会显示输出的每一行两次,每一行一个接一个。

我有一个偷偷摸摸的怀疑,这是因为这些进程要么在两个完全不同的线程中运行,它们不知道彼此的进程,但是,我不知道如何验证我的怀疑,或者,如果我是正确的,应该怎么做去做吧。我已经验证ProcessRequest了数据库中存储的每个对象只有一个实例。

有没有其他人经历过这种情况,知道为什么他们可能会运行两次,或者知道我可以做些什么来防止他们同时运行?

4

2 回答 2

6

双重作业执行的最常见原因如下:

编辑:

  • 您的应用程序部署在集群环境中,并且您尚未将 Quartz 配置为在集群环境中运行。
  • 您的应用程序被多次部署。应用程序部署两次的情况很多,尤其是在 Tomcat 服务器中。因此,QuartzInitializerListener 被调用了两次并且 Jobs 被执行了两次。如果您使用 Tomcat 服务器并在 server.xml 中明确定义上下文,则应关闭自动应用程序部署或指定 deployIgnore。设置为 true 的 autoDeploy 和 server.xml 中存在的上下文元素都导致应用程序的两次部署。将 autoDeploy 设置为 false 或从 server.xml 中删除上下文元素。
  • 您的应用程序已重新部署,但未取消计划当前进程。

我希望这可以帮助你。

于 2012-08-21T11:32:51.830 回答
2

Quartz 使用线程池来执行作业。因此,正如您所怀疑的那样,RBDDalProcess可能会在单独的线程中有单独的实例,并且计数器检查将失败。

您可以做的一件事是列出在调度程序中注册的作业(您可以使用 OB API 获取调度程序:)OBScheduler.getScheduler()

// enumerate each job group
for(String group: sched.getJobGroupNames()) {
    // enumerate each job in group
    for(JobKey jobKey : sched.getJobKeys(groupEquals(group))) {
        System.out.println("Found job identified by: " + jobKey);
    }
}

如果您看到相同的作业添加了两次,请查看用于控制作业实例化的org.quartz.spi.JobFactoryorg.quartz.Scheduler.setJobFactory方法。

还要确保在 Openbravo 的“报告和流程”表中只有一个该流程的条目。

DalBaseProcess在 Openbravo 3.0 中使用过,我无法确认您所描述的这种行为。考虑到这一点,检查 Openbravov2.50MP24 和 Quartz 的已报告错误或在Openbravo Forge论坛中发布有关您的问题的主题可能是个好主意。

于 2012-08-21T12:06:55.453 回答