一、背景

作为业务开发人员,会经常需要写一个定时任务。目前,写定时任务应用最广泛最成熟的方案是OpenSymphony开源组织在任务调度领域的一个开源项目quartz,比如要写一个定时数据同步任务,在完成quartz的相关配置后,只需要写一个jobBean_A就能基于quartz完成调度;如果要再开发一个任务,那么再写一个jobBean_B。

这样做的方式有一个地方不是很好,quartz调度与job业务耦合在一起,当任务数量越来越多,甚至达到成千上万个,对于项目本身的维护也是一个挺大的挑战。这时,会考虑将quartz任务项目拆分出来,但这样每一个任务工程都需要依赖quartz,不方便统一调度管理。为了能统一管理调度任务,又能将调度和job业务分离,我们提出云调度方案

二、架构设计

云调度中心ferrari的设计目标:

  • 调度中心本身不执行任何业务代码,只负责管理各个任务。这样的好处是,调度中心与业务job解耦,方便调度中心自身的升级维护;
  • job无需关心调度中心的内部逻辑,只需关注自身的job业务逻辑,让写一个job像写一个web action一样方便。

基于上述初衷,我们提出的云调度中心设计方案,如图:

总共分为三层:调度控制层,调度接入层,业务层。

  1. 调度控制层,基于quartz实现,主要用于管理任务调度信息,如调度job的类名、方法名、方法入参、job地址、job执行时间等;
  2. 调度接入层,主要用于接收调度控制中心的调度指令(如执行、终止任务命令),并根据接收到的任务信息(类名、方法名、入参)进行反射调用相应的任务类;
  3. 业务层,这里主要用于实现job逻辑;

这样,要开发一个任务,基本不用关心调度控制层和接入层的逻辑,只需在业务层实现任务逻辑即可。任务开发完后,在调度控制中心新增一个调度任务信息,便可接收调度中心的调度。

三、实现方案

云调度中心的实现是基于quartz,所以对quartz必须有个清楚的理解。

Quartz任务调度的核心元素是scheduler(调度器),trigger(触发器,用于定义调度时间规则) 和 job(任务),其中 trigger 和 job 是任务调度的元数据,scheduler 是实际执行调度的控制器。quartz内部的调度原理可以查看后面列举的参考文档,这里具体讲讲使用quartz的几个注意点。 ####3.1 线程池配置 quartz.properties里的线程池配置:

#Configure ThreadPool
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 15
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

Quartz 中自带了一个线程池的实现SimpleThreadPool,并通过threadCount来设置最大并发数,一般设置在10~50比较合适。 ####3.2 misfire策略 misfire,即错过的,指本来应该被执行但实际没有被执行的任务调度,一般来说引起misfire的情况有以下4种:

  • 调度控制中心因为某些原因被重启。在系统关闭到重新启动之间的一段时间里,可能有些任务会被 misfire;
  • Trigger 被暂停(suspend)的一段时间里,有些任务可能会被 misfire;
  • 线程池中所有线程都被占用,导致任务无法被触发执行,造成 misfire;
  • 有状态任务在下次触发时间到达时,上次执行还没有结束(无状态任务没有这种情况);

quartz对misfire的产生有个时间条件,超过这个设定的时间则认为是misfire,配置如下:

#Misfire
org.quartz.jobStore.misfireThreshold: 120000 #120秒
org.quartz.jobStore.maxMisfiresToHandleAtATime: 1

为了处理 misfired job,Quartz 中为 trigger 定义了处理策略,主要有下面两种:

  1. MISFIRE_INSTRUCTION_FIRE_ONCE_NOW:针对 misfired job 马上执行一次;
  2. MISFIRE_INSTRUCTION_DO_NOTHING:忽略 misfired job,等待下次触发;

ferrari使用的是第2种策略:

CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();

####3.3 调度集群设置 Quartz 中的 trigger 和 job 需要存储下来才能被使用,有两种存储方式:内存和数据库。如果将调度信息存储在内存,那么只要quartz应用重启,这些信息就会丢失,所以在生产环境中,一般都用数据库存储的方式,配置如下:

#Configure JobStore for RAM
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore
#for cluster
org.quartz.jobStore.tablePrefix = XXX_
org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.isClustered: true
org.quartz.jobStore.clusterCheckinInterval: 20000

jobStore设置为jdbcjobstore.JobStoreTX即代表数据库存储方式,由于quartz集群是通过数据表来实现并发锁控制,所以需要设置集群的节点检查轮训时间clusterCheckinInterval,这里设置为20s。 ####3.4 调度器配置 spring对quartz进行了整合,这里采用基于spring的quartz配置,如下:

 <!-- 默认 lazy-init="false"spring-context-support version: 3.2.14.RELEASE quartz version:2.2.2--><bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="dataSource" ref="dataSource" /><!-- 设置自动启动 --><property name="autoStartup" value="true" /><!--必须的,QuartzScheduler 延时启动,应用启动完后 QuartzScheduler 再启动 --><property name="startupDelay" value="20" /><!--需要overwrite已经存在的job,如果需要动态的修改已经存在的job,就需要设置为true,否则会以数据库中已经存在的为准--><property name="overwriteExistingJobs" value="true" /><property name="applicationContextSchedulerContextKey"  value="applicationContextKey" /> <property name="configLocation" value="classpath:quartz.properties"/></bean>

####3.5 quartz任务开发 基于云调度中心ferrari的架构,在调度控制中心层,我们只要开发一个quartzJobBean。在这个jobBean中,基于ferrari协议将需要执行的类名、方法名、入参、任务机器地址等信息封装成一个request,然后发送请求(ferrari用的是http请求)到任务目标机器。

在业务层,任务机器接收到调度控制中心的指令,解析出任务信息,便交给任务执行线程池,任务执行线程通过反射调用目标任务类进行执行。作为业务层,无需基于quartz做任何开发,只需开发一个普通的类(称为任务类),然后将任务信息配置到调度控制中心,便可实现调度。

四、ferrari接入说明

####4.1 maven依赖

<dependency><groupId>com.dianping</groupId><artifactId>ferrari-core</artifactId><version>1.2.4</version>
</dependency>

####4.2 web.xml配置servlet入口

<servlet><servlet-name>FerrariServlet</servlet-name><servlet-class>com.cip.ferrari.core.FerrariDirectServlet</servlet-class><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>FerrariServlet</servlet-name><url-pattern>/xxx/*</url-pattern>
</servlet-mapping>

####4.3 开始写你的任务类及方法,类名、方法、入参在新增任务时配置 ferrari新增任务界面: ####4.4 云调度中心日志接入 由于job任务不在调度中心执行,而是有另外的job服务机器执行,所以要看业务日志代码,必须登录对应的业务机器。如果job很多,又散落在各个机器,那么要查看job运行日志,效率就会比较低。为了方便日志查看,ferrari提供了日志接入方案,在log4j.xml中增加一个append配置:

<appender name="FERRARI" class="com.cip.ferrari.core.log.FerrariFileAppender"><param name="filePath" value="/data/applogs/xxx/"/><param name="append" value="true"/><param name="encoding" value="UTF-8"/><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%t]-[%M]-[%L]-[%p] %m%n"/></layout>
</appender>

其中,filePath 是日志文件夹路径。只要将日志输出在这个appender上,就能在调度控制中心远程查看业务执行的日志,如图所示:

云调度中心ferrari的实现源码请移步: https://github.com/tkyuan/ferrari 记得给star^_^ ####参考文档:

  1. http://www.cnblogs.com/davidwang456/p/4205237.html
  2. https://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/
  3. http://www.quartz-scheduler.org/

转载于:https://my.oschina.net/tkyuan/blog/678001

基于quartz的云调度中心实现相关推荐

  1. 基于 Quartz 的调度中心

    需求 服务使用集群部署(多Pod) 基础服务提供调度任务注册,删除,查看的功能 尽可能减少客户端的使用成本 开发工作量尽可能少,成本尽可能小 基于以上的需求,设计如下,调度中心非独立部署,集成在bas ...

  2. 联想基于Apache DolphinScheduler构建统一调度中心的应用实践

    导读 随着业务不断增长以及定时任务类型的多样化,联想内部需要一个统一的调度中心对任务生命周期进行管理.Apache DolphinScheduler 是一个分布式.易扩展的可视化 DAG 工作流任务调 ...

  3. 十七、.net core(.NET 6)搭建基于Quartz组件的定时调度任务

     搭建基于Quartz组件的定时调度任务 先在package包项目下,添加Quartz定时器组件: 新建类库项目Wsk.Core.QuartzNet,并且引用包类库项目.然后新建一个中间调度类,叫Qu ...

  4. 云数据中心网络遇到的问题_云数据中心面临安全问题,华为SDN解决方案有一个安全大脑...

    CNET科技资讯网 9月23日 北京消息(文/周雅):当越来越多的企业开始采用云服务,安全问题往往成为待考虑的问题.在传统IT环境中,企业默认的逻辑架构是可信的,数据在自己手里,系统部署在自己的数据中 ...

  5. 华为超大云数据中心落地贵州,这些硬核技术有利支撑“东数西算”

    摘要:在贵州建设的数据中心又该如何最大化利用算力资源,从而有效提高资源分配率,降低云资源的使用成本. 本文分享自华为云社区<华为全球最大数据中心落地贵州,这些硬核技术有利支撑"东数西算 ...

  6. SDN与NFV技术在云数据中心的规模应用

    以云数据中心为切入点,首先对SDN领域中的叠加网络.SDN控制器.VxLAN三种重要技术特点进行了研究,接下来对NFV领域中的通用服务器性能.服务链两类关键问题展开具体分析.最后,阐述了前期开展的SD ...

  7. python 分布式 调度 管理_分布式云调度处理系统

    分布式云调度处理系统. 项目参考xxl-job进行若干改动. 项目基于quartz并进行若干扩展而成,适用于公司内部做定时调度处理,方便,快捷,简单. 支持bean, groovy, shell, p ...

  8. Mendix基于腾讯云部署最佳实践

    本实践由腾讯云与西门子数字化工业软件授权发布,未经允许不得转载. 1.  概述 本文档介绍了西门子企业级应用开发平台Mendix应用快速托管到腾讯云容器服务(简称TKE)的最佳实践.该方案仅用于非生产 ...

  9. 003云数据中心基础原理笔记

    01 云数据中心代替传统数据中心 1.从IBM和Amazon的2013年案例分析 CIA项目最看重的三个主要方面的内容: 技术的展现方面.技术的解决方案方面.服务水平保障方面 CIA项目的业务本质:情 ...

  10. 基于quartz实现定时任务管理系统

    基于quartz实现定时任务管理系统 背景 说起定时任务框架,首先想到的是Quartz.这是定时任务的老牌框架了,它的优缺点都很明显.借助PowerJob 的readme文档的内容简单带过一下这部分. ...

最新文章

  1. HDU2680(SPFA算法)
  2. 使用DistilBERT 蒸馏类 BERT 模型的代码实现
  3. [架构设计]反向(或者后向)插件系统设计
  4. Linux桌面环境介绍以及优缺点分析
  5. 【短语学习】盈余量分析(earned value analysis)
  6. 普通人改变命运最关键的这几种方法
  7. 暴风集团否认暴风TV公司解散:融资事项正在加紧推进中
  8. HTML5 — 知识总结篇《VII》【图片元素】
  9. 打造自己的VC++ 6.0免安装简版
  10. Omni Recover适用于哪些IOS数据恢复方案?
  11. vue中把table导出表格excel
  12. 089 重用父类方法的两种方式
  13. 实现文字跟随鼠标移动--[转]
  14. 并发编程学习之线程池
  15. vb.net中如何结束一个线程
  16. Silverlight/WPF/WP7一周学习导读(12月6-12月12)
  17. 半导体物理学习记录——概述
  18. python抓取北京所有社区医院经纬度
  19. 基于控制台的老虎机Java Demo
  20. 树莓派ONVIF推流做网络摄像头

热门文章

  1. C#中RestoreDirectory属性
  2. Colaboratory平台+Mask R-CNN进行模型训练和实例分割
  3. 《剑指offer》面试题16——反转链表(C++)
  4. JS学习总结(6)——函数/弹出框
  5. 地图相关知识和地图打印色彩差异解决办法
  6. java param=json字符串_java解析json字符串
  7. Flink on Zeppelin (2) - Batch 篇
  8. 技术人应有的职业意识
  9. 一年Android工作经验,一举拿下百度、网易、美团、小米、快手等Offer面经
  10. FFmpeg总结(七)AV系列结构体之AVIOContext