quartz部分参数解析

前提

最近要实现一个每隔几分钟就监控rpc调用是否存活的系统,考虑到监控的rpc数量众多,因此将每个监控作为任务,方便起见使用了quartz。

quartz参数配置

下面列出了部分配置参数以及自己的理解,完整的参数配置建议参考:
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/configuration/

//实例名称,分布式下每个实例名称必须相同
org.quartz.scheduler.instanceName= jsfMonitorQuartzScheduler
org.quartz.scheduler.rmi.export= false
org.quartz.scheduler.rmi.proxy= false
org.quartz.scheduler.wrapJobExecutionInUserTransaction= false
//一次性取出的任务数,默认值是1,适合负载均衡,但不适合大量的短时任务
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=50
//一个quartz实例的主线程完成一次操作过后的停顿时间,默认30秒,
//对于大量短时任务可以适当的减小该值,弊端是增加数据库的负担
org.quartz.scheduler.idleWaitTime=30000
org.quartz.threadPool.class= org.quartz.simpl.SimpleThreadPool
//quartz执行任务的最大线程数,对于SimpleThreadPool,没有任务队列,
//新的任务到来时将阻塞到有空闲线程可用,由于这个限制,
//实际上quartz在从数据库拉取可执行任务时将根据线程数
//和batchTriggerAcquisitionMaxCount的较小值来获取可触发的任务
org.quartz.threadPool.threadCount= 50
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread= true
//当任务错过触发时间时,最忍受的最长延迟时间
org.quartz.jobStore.misfireThreshold= 60000
//使用jdbc
org.quartz.jobStore.class= org.quartz.impl.jdbcjobstore.JobStoreTX
//这里使用了自定义的driverDelegateClass,原因是公司数据库不支持blob,
//因此重写了底层关于处理blob的方法,使用varchar存储,使用json进行处理
org.quartz.jobStore.driverDelegateClass= com.jd.id.jsfmonitor.service.quartz.NoBlobJDBCDelegate
//该值表示是否datamap中所有数据都使用properties模式,即字符串,默认是false,
//这里使用了true也是为了不使用blob做的兼容,property模式下可以使用json进行统一处理
org.quartz.jobStore.useProperties= true
//关于数据源,这里可以和spring mvc使用同一个
#org.quartz.jobStore.dataSource= jsfmonitor
org.quartz.jobStore.tablePrefix= WARE_JSF_MONITOR_QRTZ_
//启用分布式
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
//默认值为0,表示一个任务可以提前多久被触发,适用于大量的任务需要触发
org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow
#org.quartz.dataSource.jsfmonitor.driver= com.mysql.jdbc.Driver
#org.quartz.dataSource.jsfmonitor.URL= jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
#org.quartz.dataSource.jsfmonitor.user= root
#org.quartz.dataSource.jsfmonitor.password= 123456
#org.quartz.dataSource.jsfmonitor.maxConnections= 30

org.quartz.scheduler.instanceId= AUTO

关于不支持blob

公司的数据库不支持blob格式,因此手动实现了driverDelegateClass,主要是通过继承StdJDBCDelegate并重写其中和blob相关的方法,主要的修改点在如下部分;

Map<?, ?> map = null;
                if (canUseProperties()) {
                    map = getMapFromProperties(rs);
                } else {
                    //map = (Map<?, ?>) getObjectFromBlob(rs, COL_JOB_DATAMAP);
                    throw new SQLException("只支持properties模式");
                }

这段代码是要从结果集当中取出任务的datamap,包括获取trigger,jobdetail等多个方法中都有该代码段,这些方法都被重写了。源代码中会判断org.quartz.jobStore.useProperties是否为true来选择加载的方式,这里我把该值设置为true,目的是为了有统一的入口可以修改从结果集当中获取数据的方式。源代码中getMapFromProperties方法仍然会按照blob的方式进行解析,并且该方法是private的,因此我自己实现了该方法,如下:

private Map<?, ?> getMapFromProperties(ResultSet rs)
            throws ClassNotFoundException, IOException, SQLException {
        Map<?, ?> map;
        String data = rs.getString(COL_JOB_DATAMAP);
        if (data == null) {
            return null;
        }
        Properties properties = JSON.parseObject(data, Properties.class);
        map = convertFromProperty(properties);
        return map;
    }

通过string的方式获取,这里对应的是存数据的时候也需要string的方式存储,建表的时候也需要将blob修改为varchar。数据的解析则通过json实现(json可能不是最节省空间的方式)。

关于quartz主线程

quartz主线程类是QuartzSchedulerThread,该类在其run方法内会每隔一段时间就从数据库中取出可以被执行的任务,执行过后会有短暂的sleep,sleep过后重复上述过程。这里单次获取的任务数上限取org.quartz.scheduler.batchTriggerAcquisitionMaxCountbatchTriggerAcquisitionMaxCount中的较小值,代码如下:

//idleWaitTime对应org.quartz.scheduler.idleWaitTime,这里now+idleWaitTime表示quartz
//可以获取的任务重最晚的触发时间,即允许任务被触发的时间在当前时间之后一段时间就
//能从数据库取出
triggers = qsRsrcs.getJobStore().acquireNextTriggers(
                                now + idleWaitTime, Math.min(availThreadCount, qsRsrcs.getMaxBatchSize()), qsRsrcs.getBatchTimeWindow())

org.quartz.scheduler.idleWaitTime的另一个作用是决定主线程在一次操作过后的暂停时间,当然这个暂停时间会减去一个相关的随机值。这里可以很清晰的看到该值会影响主线程访问数据库的频率,官方文档也强调除非有特殊原因,比如大量的任务需要调度,否则不能把该值设置过低,官方建议不能低于5000ms。

long now = System.currentTimeMillis();
                long waitTime = now + getRandomizedIdleWaitTime();
                long timeUntilContinue = waitTime - now;
                synchronized(sigLock) {
                    try {
                      if(!halted.get()) {
                        // QTZ-336 A job might have been completed in the mean time and we might have
                        // missed the scheduled changed signal by not waiting for the notify() yet
                        // Check that before waiting for too long in case this very job needs to be
                        // scheduled very soon
                        if (!isScheduleChanged()) {
                          sigLock.wait(timeUntilContinue);
                        }
                      }
                    } catch (InterruptedException ignore) {
                    }
                }
private long getRandomizedIdleWaitTime() {
        return idleWaitTime - random.nextInt(idleWaitVariablness);
    }

最后推荐两篇文章,一篇是quartz的分布式原理
http://www.icartype.com/?p=140
一篇是quartz的性能优化
http://mp.weixin.qq.com/s?__biz=MzIxMjE0MjM4NA==&mid=402443938&idx=1&sn=77f72cbf29c691668c47c4b016bdcc60#rd

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容