`

几年前写的一个任务调度模块

    博客分类:
  • Java
阅读更多
    大概是在09年下半年,参与了一个项目,当时项目有一些需要定期执行的任务,并且考虑到后续会有更多的任务需要调度,所以项目负责人决定做一个调度模块。而且,有了调度模块之后,其他项目可以重复利用,从而实现“一次编写处处可用”。这样,在有新的调度任务时,只要按照规则做一些简单的配置就可以了。最终,这个光荣的工作任务就落到了我手上。
 
    接下来说说调度模块的设计与实现思路。
 
从总体上,调度模块包括两部分:调度管理和调度执行引擎,这两部分独立部署,共用数据库。
 
一、调度管理
    调度管理主要是对任务、调度规则的配置管理。
 
1、支持的任务类型
1)URL
    可以指定需要定期调用的URL,同时可以配置相应的参数列表。这种方式,只要能通过URL进行访问的任务,都可以进行调度。
    优点:只要提供任务的URL,就可以进行调度,很灵活,配置简单。
    缺点:如果URL经过的网络比较差,调度时间稍有影响,但很细微;如果任务比较多或调度比较频繁,将会建议比较多的http连接,从设计上其实不太好。
 
2)存储过程
    可以指定需要定期调用的存储过程,同时可以配置存储过程的参数,但参数值是固定的。
 
3)实现调度任务接口方法
    系统定义了一个接口,该接口包含一个用于调度的方法。需要进行调度的任务,可以通过实现该接口,然后只要在调度管理模块进行类名全路径的简单配置,再配置调度规则,就可以实现对该任务的调度。
    另外,按照原来的设计思路,必须支持动态上传加载任务。即在项目上线运行过程中,不重启工程的情况下,可以通过上传class类、jar包任务代码,配置任务及调度规则之后,动态装载class类、jar包进行调度。
    优点:调度任务接口规范化了;动态装载任务的方式实现了任务的热装载,新增任务代码不需要重启工程。
    缺点:与使用URL的方式相比,自由度、灵活性稍差一些。
 
2、调度规则
    调度规则主要字段有:任务名称/代码、生效/失效日期、首次执行时间、任务类型(周期性/一次性)、每日(时、分、秒)/每周(周几、时、分、秒)/每月(几号、时、分、秒)、间隔(多少天/小时/分/秒)
 
二、调度执行引擎
    调度管理只是负责任务和规则的管理工作,实际的任务调度是由调度执行引擎负责实现。对任务的监测扫描,任务的启动、暂停、删除以及调度,都在这里实现。
 
    调度框架使用了比较流行的Quartz,结合Spring进行使用。其实当时还使用了另外一项批处理技术(spring batch),但事实上对于本部分的实现,它已经成了鸡肋。后来发现,去掉以后其实结构会更清晰,更易于维护。所以技术的东西,够用、适用就好了,太多太杂有时适得其反。
 
1、下面贴两张流程图
1)项目工程启动之后,调度任务的初始化过程


 
2)监测任务的工作过程


 
    监测任务每隔一段时间会调用一次,如10秒调用一次。
 
2、动态装载
1)动态状态类
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
    classLoader = ClassUtils.class.getClassLoader();
}
classLoader .loadClass(name);
 
2)动态状态装包中的类
URL url = new URL("file:" + jarPath); // jarPath为jar包的路径
URL[] urls = new URL[] {url};
URLClassLoader urlLoader = new URLClassLoader(urls, classLoader);
JarFile jarFile = new JarFile(new File(jarPath));
ZipEntry entry = jarFile.getEntry(jobNameFile); // jobNameFile中存放着所有要执行任务的类名全路径清单,按顺序存放
Scanner s = new Scanner(jarFile.getInputStream(entry));
while (s.hasNextLine()) {
    String name = s.nextLine().trim();
    Class<?> clazz = urlLoader.loadClass(name);
    ...
}
 
3、构造cron表达式
/**
 * 构造cron表达式
 */
public String getCronExpression(ExecPlan plan) {
	StringBuffer expression = null;
	if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_MONTH)) { // 每月
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" ");
		expression.append(plan.getFixedDateNum()).append(" * ?");
	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_WEEK)) { // 每周
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" ? * ");
		expression.append(plan.getFixedDateNum());
	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_DAY)) { // 每日
		expression = new StringBuffer();
		expression.append(plan.getFixedSeconds()).append(" ");
		expression.append(plan.getFixedMinutes()).append(" ");
		expression.append(plan.getFixedHours()).append(" * * ?");
	}
	return expression.toString();
}
 
 
 (转载请注明来源:http://zhanjia.iteye.com/blog/1870065)
  • 大小: 18.9 KB
  • 大小: 6.9 KB
8
6
分享到:
评论
4 楼 hersing 2013-06-03  
楼主在吗?像你咨询几个问题,现在项目中也用到了Quartz,现在我不明白的有几点,希望楼主有时间可以给我解惑。
1.启动工程时,初始化调度任务,我自己的代码是这样的:

public Scheduler scheduler;

/**
* 初始化
*/
public void initSchedule(){
try {
scheduler.start();
} catch (Exception e) {
e.printStackTrace();
}

List<DPScheduler> list=getAllScheduler();
for(DPScheduler dScheduler : list){
scheduleJob(dScheduler);
}
}

public void scheduleJob(DPScheduler dScheduler){
try {
JobDetail jobDetail=new JobDetail(dScheduler.getSchedulerNm(),scheduler.DEFAULT_GROUP,QuartzController.class);
CronTrigger ct = new CronTrigger(dScheduler.getSchedulerNm(),scheduler.DEFAULT_GROUP);
ct.setCronExpression(dScheduler.getProps());
ct.setStartTime(dScheduler.getBeginDate());
ct.setEndTime(dScheduler.getEndDate());
scheduler.scheduleJob(jobDetail, ct);
} catch (Exception e) {
e.printStackTrace();
}
}
我不明白的就是这个,一个scheduler的创建是通过SchedulerFactory来实现的,但是如果按照我的代码,至少说没有一个SchedulerFactory,这点不太明白。

2.其实这样的话,你自己配置的所有的scheduler已经准备就绪了,如果说再在页面中运行一个scheduler的话,其本质是否就是根据这个scheduler的ID去修改这个scheduler呢?

3.还希望楼主贴下初始化Scheduler的代码。感谢!
3 楼 javaboy2010 2013-05-24  
很不错啊! 能分享出代码吗?谢谢.
2 楼 zhanjia 2013-05-17  
Mybeautiful 写道
能不能分享下代码?

呵,有了思路之后,实现起来就容易多了。几年前的思路,不够完美,但基本够用。
这个属于公司项目的模块,不方便提供啊...
1 楼 Mybeautiful 2013-05-17  
能不能分享下代码?

相关推荐

    【车间调度】基于模拟退火求解车间调度问题matlab源码.zip

    本资料包含的"【车间调度】基于模拟退火求解车间调度问题matlab源码.zip"是一个MATLAB实现的实例,MATLAB是一种广泛用于数值计算、符号计算和数据分析的高级编程环境。MATLAB代码通常具有直观的语法,适合进行算法...

    中心化的作业调度系统,定义了任务调度模型,实现了任务调度的统一管理和监控。.zip

    它由Sun Microsystems(现在是Oracle Corporation)的James Gosling等人在1995年推出,被设计为一种简单、健壮、可移植、多线程、动态的语言。Java的主要特点和优势包括以下几个方面: 跨平台性(Write Once, Run ...

    PSO+ALP_rollinghorizon_滚动时域_粒子群调度_粒子群算法_PSO_源码.zip

    该策略的特点是在每个时间步长内,只考虑当前及未来有限的时间段,计算出最佳决策,然后立即执行,并更新模型进入下一个时间段。这种分阶段处理的方法既能保证实时性,又能兼顾长期规划,适用于电力系统调度、生产...

    论文研究-手机阅读平台仓库管理模块的设计与实现 .pdf

    在设计手机阅读平台的仓库管理模块时,系统实现了几个主要的功能:元数据管理、任务调度与监控、数据血缘分析。元数据管理是指对数据的描述信息进行组织和管理,这些元数据通常包括数据源、数据格式、数据模型等,...

    任务书ssm516基于HTML和JS物资物流系统的设计与实现+vue任务书.doc

    【物资物流系统设计与实现】基于HTML和JS的物资物流系统设计旨在构建一个适用于初创物流公司的低成本、功能实用的信息管理平台。系统采用B/S架构,前端利用HTML和JavaScript技术,结合Vue框架,后端则使用JSP技术,...

    嵌入式操作系统调度机制的研究* (2009年)

    2. **调度算法管理器**:这是一个核心模块,负责管理和调度不同的算法插件。它能够根据用户的选择加载相应的调度算法,并在运行时根据实际情况动态调整调度策略。 3. **用户界面**:提供了一个直观的图形界面,用户...

    Transformers_Models 变压器模块

    在"Transformers_Models 变压器模块"中,我们可以探讨以下几个关键知识点: 1. **自注意力机制**:自注意力允许模型在处理每个位置时考虑所有其他位置的信息,通过计算不同位置之间的相似度来生成权重,形成对输入...

    freertos.pdf

    FreeRTOS 是一个开源的实时操作系统内核,由 Richard Barry 于 2003 年创立。它的设计初衷是为了给嵌入式系统提供一个简单、可移植且易于使用的实时调度解决方案。凭借其轻量级的设计和高度的灵活性,FreeRTOS 成为...

    Spring quartz 定时 实例

    Spring Quartz 是一个强大的任务调度框架,它允许开发者在Spring应用中轻松地定义和执行定时任务。Quartz 是一个开源的作业调度库,可以用来创建、调度和执行作业,而Spring框架则提供了与Quartz集成的模块,使得在...

    ucOS2.52.rar_ucos2.52

    2. **优先级继承**:这是一个防止死锁的机制,当一个任务持有信号量并且被更高优先级的任务阻塞时,ucOS II会暂时提升该任务的优先级,确保高优先级任务能及时运行。 3. **信号量**:信号量用于同步和资源保护,...

    dateutil模块包

    Python的`dateutil`模块是Python标准库`datetime`模块的一个强大扩展,它提供了一系列高级的时间解析和计算功能。在OpenERP7(现称为Odoo7)开发中,`dateutil`模块扮演了重要的角色,因为它能帮助开发者处理复杂的...

    ITRON系统使用方法.doc

    ITRON最初由日本电子情报技术产业协会(JEITA)于1987年制定,是一个针对微处理器和嵌入式系统的实时操作系统规范。它的主要目标是提供一种标准化的接口,以便于开发者能够在不同的硬件平台上轻松移植软件。ITRON的...

    VxWorks简要手册.doc

    - **任务管理**: VxWorks支持多任务环境,每个任务都有一个优先级,任务调度基于优先级抢占和轮转调度机制。 - **通信与同步机制**: 包括信号量、邮箱、消息队列等多种机制,用于任务间的通信与同步。 - **内存管理*...

    基于服务网格的动态负载平衡调度算法研究 (2007年)

    为了解决这一问题,需要一个有效的负载平衡调度系统,以确保任务能够更合理地分配到各个网格节点上,从而提高整个系统的效率和资源利用率。 #### 动态负载平衡调度模式 传统的调度算法通常分为集中式和分布式两种...

    Python库 | TGScheduler-1.6.1-py2.6.egg

    TGScheduler是一个基于Python开发的高效、易用的调度框架,主要用于自动化任务的管理和执行。版本1.6.1-py2.6.egg是针对Python 2.6编译的,这表明该库可能不支持Python 3.x版本。在Python社区中,Python 2于2020年1...

    Linux操作系统简介-英文

    - **调度**:支持实时和非实时任务调度策略。 - **输入输出管理**:提供高效的磁盘调度和页缓存机制。 - **虚拟文件系统**:支持多种文件系统类型。 - **网络功能**:支持数据发送和接收等功能。 #### 进程和线程...

    Python-基于python35使用基于Linux的任务命令CNIC自动打卡程序

    Python3.5是Python语言的一个版本,它在2015年发布,引入了许多新特性,比如asyncio模块,用于实现异步I/O,增强了字典的性能,并且支持了更多的上下文管理协议。在这个项目中,我们使用Python3.5来编写一个自动打卡...

Global site tag (gtag.js) - Google Analytics