quartz分布式搭建,把单机模式修改为分布式

quartz的分布式搭建也很多,但是由于每个项目的结构不同,采用的方式也不同。我们公司的项目原来采用的quartz的单机版。但是由于采用redis作为缓存,两个tomcat作为应用服务器。那么quartz理所应当的要进行分布式升级。

先看看原来采用的方式。

public class QuartzManager {
    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
    private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";  
    private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";  
 

  //QuartzTask  为自己建立的定时任务表表结构以及数据格式是这个样子的,我们的定时任务不是采用xml的定时器方式存储的,是放在了数据库里面


    public static void addJob(String jobName, Class cls, String time,QuartzTask task) {  
        try {
             Scheduler sched = gSchedulerFactory.getScheduler();
             
             JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类 
             jobDetail.getJobDataMap().put("task", task);
             
             CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
             
             trigger.setCronExpression(time);// 触发器时间设定 
             sched.scheduleJob(jobDetail, trigger);
             // 启动 
             if (!sched.isShutdown()) {
                 sched.start();  
             }
        } catch (Exception e) {
            throw new RuntimeException(e);  
        }
    }

这种方式为单机模式,容器以及任务全部存在内存中,是不合适的。我这块想了一下,应该改动这一块就可以了。

第一:修改spring的配置文件,因为容器也就是Scheduler的对象不应该在对象里面创建,应该交给spring进行管理。

修改第一步:

创建定时器表机构,这个在网上可以搜到,就是这个样子的,打开,然后执行,如果执行出错,表里面有一句话TYPE=InnoDB;

改成engine=InnoDB就可以了

第二步,创建quartz.properities文件,文件内容

# 调度器实例的名字,使用默认的DefaultQuartzScheduler就好
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
# 调度器实例的ID, 选择AUTO
org.quartz.scheduler.instanceId:AUTO
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
# 跳过更新检查
org.quartz.scheduler.skipUpdateCheck:true
# 配置线程池
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true
#
# quartz默认的是将job信息存储在内存中,quartz集群必须将job信息持久化到数据库中
org.quartz.jobStore.dataSource = dataSource
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.misfireThreshold:60000
############
# 以指示JDBCJobStore将JobDataMaps中的所有值都作为字符串,因此可以作为名称 - 值对存储而不是在BLOB列中以其序列化形式存储更多复杂的对象。从长远来看,这是更安全的,因为您避免了将非String类序列化为BLOB的类版本问题
org.quartz.jobStore.useProperties:false
#quartz数据表的前缀,quartz的数据表在 quartz-2.2.3\docs\dbTables 文件夹中,
#选择对应的数据库版本,将数据库创建出来
org.quartz.jobStore.tablePrefix:QRTZ_
# 最关键的  是否支持集群 选择true
org.quartz.jobStore.isClustered:true
org.quartz.jobStore.clusterCheckinInterval:15000

第三步:修改spring的配置文件,把容器交给spring管理

加入一个bean为

<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:/quartz.properties" />
        <property name="dataSource" ref="dataSource" />
        <!-- 如果这个覆盖配置为false,quratz启动以后将以数据库的数据为准,配置文件的修改不起作用。-->
        <property name="overwriteExistingJobs" value="true" />
        <!-- 为了在Job中进行属性的注入,所必需的类 -->
       <!--<property name="autoStartup" value="false" />-->
        <property name="startupDelay" value="1"/>
    </bean>

第四步:修改QuartzManager的addJob方法

public class QuartzManager {
    private static Logger logger=Logger.getLogger(QuartzManager.class);
    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
    private static String JOB_GROUP_NAME = "EXTJWEB_JOBGROUP_NAME";  
    private static String TRIGGER_GROUP_NAME = "EXTJWEB_TRIGGERGROUP_NAME";
    private static Scheduler scheduler;
    
    
    public static Scheduler getScheduler() {
        return scheduler;
    }

    public static void setScheduler(Scheduler scheduler) {
        QuartzManager.scheduler = scheduler;
    }
    public static void addScheduler(Scheduler schedulerOther){
        scheduler=schedulerOther;
    }

    public static void addJob(String jobName, Class cls, String time,QuartzTask task) {  
        try {
             JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);// 任务名,任务组,任务执行类 
             jobDetail.getJobDataMap().put("task", task);
             
             CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);// 触发器名,触发器组
             
             trigger.setCronExpression(time);// 触发器时间设定 
             scheduler.scheduleJob(jobDetail, trigger);
             // 启动 
             if (!scheduler.isShutdown()) {
                 scheduler.start();  
             }
        } 
        catch(org.quartz.ObjectAlreadyExistsException e){
            logger.info("已经存在定时任务e"+e);
        }
        catch (Exception e) {
            throw new RuntimeException(e);  
        }
    }

这个时候scheduler是无法注入的,也就是空,我们的项目采用项目启动时加载定时任务,那么需要在项目启动的时候加载一下

这样,注入的参数就进去了。

这样,项目的分布式搭建成功。。。修改原来的项目只需要这四步

把碰到的错误分享一下。

第一:出现这个错误OPTION SQL_SELECT_LIMIT=5,这个错误是mysql连接驱动版本过低导致的,我原来的版本是mysql-connector-java-5.1.18,升级到5.1.31,这个问题就解决了。升级的时候原来的版本要删除掉,一定要删除掉,保证项目只有一个connector才可以,我就是升级了也不好使,最后只保留一个才可以的。

第二:出现这个错误

Couldn't store job: JobDataMap values must be Strings when the 'useProperties' property is set.  Key of offending value:

修改一下org.quartz.jobStore.useProperties:false就可以了。具体的原因,我看了一下,如果设置为true,需要把存错的键值对当做字符串来进行保存,报错信息也是键值对无法按照string进行报错,所以需要改成false。这样就不报错了

第三:database is null

在做分布式quartz里面,数据库需要命名,我的程序是用jdbc连接,采用bonecp作为连接池,也就是说在我没修改定时任务的分布式的时候,配置文件里面就是dataSource这个数据库连接池了。所以需要在quartz的配置文件里面加上org.quartz.jobStore.dataSource = dataSource,记住,这个数据库的名字要统一,不要写乱了。否则总会报数据库连接的错误。

 

 

顺便说一下,分布式搭建完毕,业务处理还没完事,剩下的都是业务问题,可以自行处理

 

 

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Quartz是一种广泛使用的分布式定时作业调度框架,可用于在多台服务器上触发执行一组作业。以下是Quartz分布式定时任务框架的搭建步骤: 1. 安装数据库 Quartz框架需要一个持久性存储器来保存作业调度信息。选择一个数据库(如MySQL或Oracle)并创建Quartz的表结构。 2. 配置Quartz实例 在Quartz中,每个实例代表一个独立的调度器,可以在其上启动和停止作业调度。要配置Quartz实例,需要在代码中指定一些配置属性,例如数据库连接信息和调度器的名称。 3. 创建作业和触发器 在Quartz中,作业代表要执行的代码逻辑,而触发器则指定作业何时运行。可以使用Cron表达式来指定触发器的运行时间。要创建新的作业和触发器,请使用Quartz的API。 4. 创建分布式Quartz实例 为了使Quartz分布式环境中运行,需要在所有服务器上创建Quartz实例。这些实例应该使用相同的数据库,并且应该使用相同的配置属性。 5. 配置集群 在分布式环境中,Quartz需要一种机制来协调调度器的运行。可以通过使用第三方插件(如Terracotta)或Quartz提供的基于数据库的集群实现来实现这一点。 6. 启动Quartz实例 一旦完成了配置和集群设置,可以启动Quartz实例并开始调度作业。要启动Quartz实例,需要使用Quartz的API方法。 总之,搭建Quartz分布式定时任务框架需要一定的技术和经验。最好在熟悉Quartz框架之前不要尝试这个任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值