当前位置: 首页 > 知识库问答 >
问题:

Quartz在集群环境中不能正常工作

南宫喜
2023-03-14

我在WebSphere8.5.5上使用Quartz-2.2.3,在集群环境中,我有2个节点,每个节点上有3个JVM。

我正在应用程序启动时配置作业。

问题是作业在每个节点上配置一次,我希望它在两个节点上只配置一次,而不是每个节点上都配置一次。

我的配置如下:

QuartzConfig.Properties:

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName = MyJobScheduler
org.quartz.scheduler.instanceId = AUTO
#org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer = true

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate 
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000

#============================================================================
# Configure Datasources  
#============================================================================

org.quartz.dataSource.myDS.driver = com.microsoft.sqlserver.jdbc.SQLServerDriver
org.quartz.dataSource.myDS.URL = jdbc:sqlserver://mydbserver:51803;databaseName=quartz 
org.quartz.dataSource.myDS.user = quartz
org.quartz.dataSource.myDS.password = quartz
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery=select 1

#============================================================================
# Configure Shutdown Plugin  
#============================================================================

org.quartz.threadPool.makeThreadsDaemons=true
org.quartz.scheduler.makeSchedulerThreadDaemon=true
org.quartz.scheduler.interruptJobsOnShutdown=true
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true

ApplicationContextListener:

public class ApplicationContextListener implements ServletContextListener {

    private StdSchedulerFactory factoryMyAppJob;

    @Override
    public void contextInitialized(ServletContextEvent event) {
        configureQuartzJobs(event.getServletContext());
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        try {
            factoryMyAppJob.getScheduler().shutdown(false);
        } catch (SchedulerException e) {
            AppLogger.log(e);
        }
    }

    private void configureQuartzJobs(ServletContext servletContext) {

        String currentTime = new SimpleDateFormat("dd_MM_yyyy_HH").format(new Date());
        String myAppGroup = "myAppGroup";
        String myAppJob = "myAppJob";


        try {



            JobDetail job = JobBuilder.newJob(myAppJob.class).withIdentity(myAppJob, myAppGroup).build();

            Trigger triggerMyApp = TriggerBuilder.newTrigger().withIdentity(myAppJob, myAppGroup)
                    .withSchedule(simpleSchedule()
                            .withIntervalInMinutes(3).repeatForever())
                    .build();

            Properties propsMyAppJob = new Properties();

            boolean production = ConfigurationUtils.isProductionEnvironment();

            if (production) {
                propsMyAppJob.load(this.getClass().getClassLoader().getResourceAsStream("quartzConfig.properties"));
                factoryMyAppJob = new StdSchedulerFactory(propsMyAppJob);
            } else {
                factoryMyAppJob = new StdSchedulerFactory();
            }
            Scheduler scheduler = factoryMyAppJob.getScheduler();

            if (scheduler.checkExists(job.getKey())) {
                scheduler.deleteJob(job.getKey());
            }

            scheduler.scheduleJob(job, triggerMyApp);

            scheduler.start();


        } catch (ObjectAlreadyExistsException oae) {

        } catch (Exception e) {
            AppLogger.log(e);
        }
    }

}

共有1个答案

孟谭三
2023-03-14

造成这种行为的原因可能有很多。配置似乎是正确的。

Quartz文档提到以下内容:

永远不要在单独的计算机上运行集群,除非它们的时钟使用某种形式的时间同步服务(守护进程)进行同步,该服务非常定期地运行(时钟之间必须在一秒之内)

还有一个:

不要针对运行(start()ed)的任何其他实例的同一组数据库表启动(scheduler.start())非集群实例。您可能会得到严重的数据损坏,并且肯定会经历不稳定的行为。

这两者都可以成为集群不能正常运行的一个有效原因。

 类似资料:
  • 问题内容: 我希望在我的应用程序中使用石英调度程序,因为我有一个集群环境,并且想保证每小时只能运行一个工作实例。我的问题是…我是否必须使用JDBC作业存储库或某种形式的作业数据“外部”存储库,以确保集群中只有一个实例在任何给定的时间运行该作业,或者对Quartz来说,还有更多的魔力我知道吗? 问题答案: 是的,您需要使用JDBC- JobStore或TerracottaJobStore来启用节点相

  • 我试图运行一个读取环境变量的应用程序,该环境变量包含大约22K个字符的JSON。项目设置告诉我使用来正确配置它,但是当我使用windows时,这些命令不起作用。 我尝试使用GUI环境变量将文件的内容复制到变量中,但是它的输入会将值截断到一定的限制,这个限制甚至不到文件的一半。在此之后,我尝试使用Powershell和以下命令设置变量: 然后用以下命令保存结果:

  • 相关:Quartz群集-服务器启动时触发器重复 null 这是很好的,但我担心的是,当两个实例完全同时启动时,可能会出现竞争情况。因为在这段代码周围没有全局锁,集群中的所有节点都将尊重它,如果两个实例同时联机,我可能会得到重复的作业或触发器,这就违背了这段代码的要点。 在集群环境中是否有自动定义Quartz作业和触发器的最佳实践?还是我需要自己设置锁?

  • 我有在集群中运行,并且我得到定期运行的作业。该作业在一台计算机中启动,其他计算机将保持到下一个执行时间。 我现在想要的是,如果前一次调用还没有完成,则延迟作业调用。例如: 即使这样也是可以接受的: 我使用了类似触发器的cron表达式,它每10分钟触发一次()。

  • 我有一个有两个节点的集群,它连接到同一个数据库,还有一个调度作业,由Quartz调度程序每10分钟启动一次。在quartz.properties中设置。 我感兴趣的是,调度程序是否会为同一节点发出作业,直到每隔10分钟可到达该节点为止,或者它使用某种算法来确定哪个节点将执行该作业。 我在文档(http://www.quartz-scheduler.org/documentation/quartz-

  • 要求是定期运行一个Java应用程序(例如每天),向客户发送电子邮件/短信通知。环境是集群/高可用性,其中多个节点将同时处于活动状态。该应用程序将部署在所有节点上,但只有一个节点应该启动并运行,即使所有节点都配置为运行。如何实现这一点。在Java应用中,使用了石英调度器。 还需要一些关于如何在Linux机器上部署这个Java应用程序的指导(像Cron作业或其他一些方式)。要求是,这个应用程序应该在服