详解Quartz集群

随着业务量的增长,单机版Quartz已经难以应对分布式任务管理的需求,此时集群版Quartz就迎刃而解了。集群版Quartz的优点是可以将多台机器作为工作节点来执行任务,这个方案可以提高任务的可靠性、性能和吞吐量。接下来,将从多个方面详细介绍集群版Quartz的实现原理和使用方法。

一、配置文件

Quartz集群的配置可以放在属性文件中,集群中每个节点都需要使用相同的配置文件。下面是一个简单的示例:

org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

其中,”org.quartz.scheduler.instanceName”和”org.quartz.scheduler.instanceId”是必须的。

二、消息通讯

Quartz集群依靠JDBC或者RMI方式进行消息通讯,以实现不同节点之间的任务调度信息共享。在消息通讯的过程中,需要注意下面的事项:

1、消息通讯组件不能够出现重复id的节点;

2、消息通讯组件的状态一定要准确。

同时,集群中所有节点的数据库连接信息必须相同。

三、任务执行原则

在Quartz集群模型中,所有的任务都必须实现Job接口,并且该接口应该是StatefulJob的子接口。StatefulJob接口要求任务必须是有状态的并且支持并发执行。这个要求是Quartz集群正常运行必须遵守的规则,并且可以通过实现StatefulJob接口来实现。

为了确保任务被正确分配到集群中各个节点,我们需要在任务类的添加注解@PersistJobDataAfterExecution。这个注解会在执行任务之前保存任务当前状态,并在任务执行完成后更新状态到数据库。这种方式可以确保任务能够正确的在不同节点之间传递。

四、任务负载均衡

任务负载均衡是Quartz集群中特别重要的一个方面。Quartz使用平衡负载策略以确保在集群中任务的平衡的分配。

四种负载均衡策略如下:

1、默认的负载均衡策略:按照最近的一次执行时间靠前的优先被执行;

2、Round Robin策略:所有节点轮流执行任务,每个节点会轮流执行一次。

3、随机策略:随机挑选一个节点去执行任务。

4、基于权重的策略:按照节点配置的权重来分配任务,权重大的节点分配到的任务数量也会比较多。

下面是一个TaskDispatchSelector的示例,可以用来选择节点:

public class TaskDispatchSelector implements LoadBalanceTaskDispatcher{

    public void dispatchTask(List ctxs) {

        JobExecutionContext selectedContext = null;
        try {
            //......

            //根据权重选择节点
            selectedContext = new WeightedLoadBalancedScheduler().instanceIdSchedulerMap.entrySet().stream().max(Comparator.comparingInt((entry) -> entry.getValue().getThreadPool().getBusyThreadCount())).get().getValue().getContext();

            //......

            selectedContext.getScheduler().triggerJob(selectedContext.getJobDetail().getKey());
        } catch (Exception e) {
            throw new MyException("Dispatch Quartz Task Fail.", e);
        }
    }
}

五、运行模式

可以在两种运行模式之间切换:

1、只读模式:节点向集群中获取任务并执行。

2、读写模式:节点不仅获取任务,还会去分配或者删除任务。

可以使用JobStoreCMT来实现读写模式。下面是一个JobFactory实现的示例:

public class JobFactory extends AdaptableJobFactory {

    @Autowired
    ApplicationContext applicationContext;

    /**
     * 实例化任务类
     * @param bundle
     * @param method
     * @return
     * @throws Exception
     */
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        JobDetail jobDetail = bundle.getJobDetail();
        Class jobClass = jobDetail.getJobClass();
        return applicationContext.getBean(jobClass);
    }
}

六、集群初始化及关闭

对于集群的初始化,需要确保所有节点都按照相同的配置启动JobScheduler。关闭集群时需要调用shutdown()方法,不要在代码中手动关闭Scheduler。

下面是一个启动和关闭Quartz集群的示例:

public class QuartzClusterRunner {

    public void start() {
        try {
            // 初始化Quartz
            SchedulerFactory sf = new StdSchedulerFactory("quartz.properties");
            Scheduler scheduler = sf.getScheduler();

            //监听Quartz scheduler的启动与关闭事件,和job调度事件
            scheduler.getListenerManager().addSchedulerListener(new MySchedulerListenerAdapter());

            scheduler.start();
            LOGGER.info("Quartz Scheduler started...");

        } catch (Throwable e) {
            LOGGER.error("Quartz Scheduler start error: {}", e.getMessage(), e);
        }
    }

    public void stop() {
        try {
            LOGGER.info("Shutting Quartz Scheduler down...");
            SchedulerFactory sf = new StdSchedulerFactory();  //注意这里没有指定属性文件
            Scheduler scheduler = sf.getScheduler();
            scheduler.shutdown();
            LOGGER.info("Quartz Scheduler shut down.");
        } catch (Throwable e) {
            LOGGER.error("Quartz Scheduler stop error: {}", e.getMessage(), e);
        }
    }
}

致谢

本文档参考了官方文档和网上的一些文章,特此致谢:

1、Quartz官方文档:

http://www.quartz-scheduler.org/

2、博客:

http://blog.csdn.net/endymionwang/article/details/7329144

http://gold.xitu.io/entry/5691b98c60b2ff006f6d741d

原创文章,作者:MSZXV,如若转载,请注明出处:https://www.506064.com/n/371817.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
MSZXVMSZXV
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相关推荐

  • 使用Go-Redis获取Redis集群内存使用率

    本文旨在介绍如何使用Go-Redis获取Redis集群的内存使用率。 一、Go-Redis简介 Go-Redis是一个用于连接Redis服务器的Golang客户端。它支持Redis…

    编程 2025-04-28
  • Redis5.0集群扩容用法介绍

    Redis是一个内存数据库,越来越受到开发者的欢迎。在开发中,我们经常需要考虑Redis集群的扩容问题。而Redis5.0针对集群扩容方面进行了多项优化和改进,本文将从多个方面详细…

    编程 2025-04-27
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25
  • Python输入输出详解

    一、文件读写 Python中文件的读写操作是必不可少的基本技能之一。读写文件分别使用open()函数中的’r’和’w’参数,读取文件…

    编程 2025-04-25
  • Python安装OS库详解

    一、OS简介 OS库是Python标准库的一部分,它提供了跨平台的操作系统功能,使得Python可以进行文件操作、进程管理、环境变量读取等系统级操作。 OS库中包含了大量的文件和目…

    编程 2025-04-25
  • nginx与apache应用开发详解

    一、概述 nginx和apache都是常见的web服务器。nginx是一个高性能的反向代理web服务器,将负载均衡和缓存集成在了一起,可以动静分离。apache是一个可扩展的web…

    编程 2025-04-25
  • git config user.name的详解

    一、为什么要使用git config user.name? git是一个非常流行的分布式版本控制系统,很多程序员都会用到它。在使用git commit提交代码时,需要记录commi…

    编程 2025-04-25
  • 详解eclipse设置

    一、安装与基础设置 1、下载eclipse并进行安装。 2、打开eclipse,选择对应的工作空间路径。 File -> Switch Workspace -> [选择…

    编程 2025-04-25
  • Linux修改文件名命令详解

    在Linux系统中,修改文件名是一个很常见的操作。Linux提供了多种方式来修改文件名,这篇文章将介绍Linux修改文件名的详细操作。 一、mv命令 mv命令是Linux下的常用命…

    编程 2025-04-25

发表回复

登录后才能评论