隔叶黄莺 The Blog of Unmi

〖隔叶黄莺三四声,挂壁飞瀑千万尘。若是人间无净土,此处为何妙语真! 隔叶黄莺四字,本非取自此句,而有寄寓他意,因见妙语,亦与予心合!〗

BlogJava 首页 新随笔 联系 聚合 管理
  380 Posts :: 106 Stories :: 1178 Comments :: 0 Trackbacks

第一章.  企业应用中的作业调度

    ·什么是作业调度

    ·作业调度为什么说是重要的

    ·企业应用中的作业调度

    ·非企业应用中的作业调度

    ·作业调度与工作流

    ·关于作业调度其他可选择方案


1. 什么是作业调度

“作业”,这一技术述语上的概念,又让我们回到了大型机的年代,那时候,用户/程序员提交一叠穿孔卡片或者纸带(上面描述了一个作业)给操作人员,由操作人员帮忙执行那些作业。用户等待作业执行完后,回到主机那边取自己的卡片和打印出来的输出结果。

因为不是每一个作业要求立即被执行,所以作业可以被安排在将来的某个时候执行。比如说,一个系统管理员每天晚上可能有一份要执行的作业列表:

    · 10:00 PM: 运行患者信息文件的上载作业

    · 11:00 PM: 运行销售数据报表生成

    · 11:59 PM: 进行数据库的备份


作业调度通常是指运行一个批量的作业或称之谓批处理。这种批处理作业一般都是放在后台运行并且不需要与用户交互。现在,显著增多的多样性的任务已代替了早先的批量作业。在一个大的组织中每天的每小时跑上百个作业已属普遍。并且作业的规模与复杂性仍在持续的上扬,因此批量作业和作业调度器也就随需应生。

2. 作业调度为什么说是重要的

俗话说,“时间就是金钱。”,过高的资源投入到枯燥的任务中无疑是金钱和资源的浪费。随着业务流程复杂性的提升,自动化流程也更能显现出它的有益之处来。图 1.1 说明了这一问题。

图1.1 任务规规模越大、越复杂、越频繁的被执行,那么能从自动化中获益也越大


人之所以称之为人,国为我们犯错误的频度远高于电脑。把一系列任务自动安置到一个作业中,然后再为这个作业创建一个调度器,到时这个作业就会自动执行了。相对于人的手工处理,我们可以减少大多数的出错机会。

作业调度器的另一个优点体现在伸缩性。我们也许能一个小时中手工完成10或20个作业,但是随着每小时处理作业数量的增加,我们就更难杜绝不在作业中引入错误。但如果借助于作业调度,只会受到硬件资源的影响了。

所以我们能着实的说通过作业调度那样自动化处理相对于手工来说,至少为我们提供了以下三个优点:

    ·资源使用效率更高

    ·更少的出错机率

    ·更高的伸缩性


3. 企业应用中的作业调度

“企业应用”一词,如今经常会被我们无意识间提及,然而似乎现在还没有对它一个准确的定义。但对于在本书中这一词的意义,我们只要建立起这样一个概念:作为某一组织的一部份而存在的软件系统或程序。这个系统可以是一个大型机上的、或者是一个C/S结构的、或者就是一个J2EE应用。真实世界中的例子就是,作业调度器能在那个系统上大量的使用。以下的几个场景,尽管没有详尽的进行描绘,也涉及到了现今应用软件常常遇到的场景。

场景 #1: 邮件提醒和告警

许多网站(不管是商业的还是别的)允许用户提供用户名和密码注册一个帐户。出于安全考虑,一个好的做法是让用户密码每隔一段时间过期失效,比如说90天的周期。这种情况下,你可以创建一个作业,让它每天午夜运行一次,并且向离过期时间不到三天的所有用户发邮件提醒。这里可以恰到好处的用到作业调度器。图 1.2 描绘了密码这个提醒作业。

图 1.2  密码过期的作业每晚发送邮件给密码很快会过期的用户



除了发过期的密码信息,网站还可以发送其他的告警或提醒(可不是垃圾邮件哦)。一个作业调度器还能够用在类似的其他方面。

场景 #2: 执行文件传输操作

许多商家需要和他们的供应商或客户作信息集成。一种集成的方式就是进行数据文件的交换。可以采用实时的方式,例如SOAP协议,但是许多时候却不需要实时性,代之以异步的方式,譬如用FTP协议来发出或取所要的文件。

下图描绘了一个劳工补偿局每天早上收到一些包含患者及事故信息的文件。公司可以雇一个人每天早上手工的检出FTP服务器上的文件。作为另一个更好的选择就是可以写一个作业,让它每天早上扫描FTP服务器,如果有文件的话,把文件内容处理后插入到患者数据库中去。让作业调度器代劳后,这个职员再也不用手工去上FTP检查文件,而可以为公司做更多别的更有意义的事情。图1.3 描绘了文件传输的操作。

图 1.3. 文件传输的作业检查FTP站点,把患者信息文件处理到数据库中。



场景 #3: 创建销售报表

公司经营由盈亏账目所驱动,其中一个很重要的事情就是经营管理者和财务人员需要拿到最终收入和毛利数据进行分析。抽取销售报表数据可能非常的慢并且很耗资源,因为这通常需要联合多个表从中查询出上千条记录。一个更好的解决途径是在晚上计帐和计价结束后,运行一个作业,让它去生成一些临时表或视图为报表程序所用。创建临时表或视图的方式,使报表生成更具动态特性,而且用户也用不着平白去等待报表的生成,一些报表工具,如水晶报表 XI(Crystal Reports XI) 本身就包含了作业调度器(见图1.4)。

图 1.4. 销售数据报表程序执行为销售团队产生收入和毛利信息


4. 非企业应用中的作业调度

Quartz 对于许多非企业环境的应用也是很有帮助的。例如,假定你有一个独立的应用程序,事件是基于时钟而不是鼠标的点击激发的。这时候你就可以把Quartz构建到这个应用程序中来,并且安排事件能周期性的被触发。

另一例子是,你也许正想查询数据库并发送邮件,而邮件接受者正是基于这些数据得到的。(译者注:真有些搞不明白)

5. 作业调度与工作流

作业调度不是工作流,理解这一点很重的要。它们常被同时应用于一个方案中,但它们是两个截然不同的解决办法,并且都可孤立使用。一个作业通常由几个步骤组成。我们回过头来看前面提到的那个密码过期的作业,实质上它是由三个步骤所组成。

   1. 获取到密码将要过期的用户列表

   2. 为列表中的用户各自发送一个邮件

   3. 更新记录,下次就能知道哪些邮件发送过

这个作业可以使用工作流的优点,作业的每一部份恰好对应着工作流的每一个步骤。这并非意味着离开了工作流,作业调度会有些糟。这是普通的下一步、下一步简单操作。只要作业调度框架与第三方工作流能轻便的解决问题,就是好的。更多的关于Quartz和工作流的内容将会在第十四章,“使用Quartz和工作流”详解。

6. 关于作业调度其他可选择方案

正如你所知,这本书是讲Quartz的,但是Quartz的可替代方案呢?当我们比较作业调度方案的时候肯定要提到别的同类应用,那么现在就来简单介绍一下它们。

Java SDK Timer 和 TimerTask 类

java.util.Timer和java.util.TimerTask这两个类是自1.3版本才加入到JDK中来的。这两个新类可以实现一个最基本的调度器。也就只能作为我们理想的完整调度器框架的一个小的部件。任何严格意义的作业调度器都提供直接指定执行时间,存储作业信息到多种介绍和使用钩子进行定制及其他更多的功能。单纯靠JDK的那两个类还不足以构建一个真正的作业调度器。JAVA的Timer类也没办法对作业和触发器作相应的组织,使用每任务一个线程,而不是线程池的方式,还有其他不足之处难以成全其实现一个完全意义的作业调度器。

本土方案

从前面提到的Timer和TimerTask类来看,我们很容易低估创建一个灵活的、并且日后可扩展的作业调度器所作出的努力。创建一个作业调度器也不视之为微不足道的活儿。它需要的不仅仅是Java线程方面的专业技术,还需要解决其他更复杂的课题。如果你没有这方面成熟的专业知识,别想着作业调度器能直接随意一份草稿能一蹴而就。

商业解决方案

现在市面上也能见到不少商业的作业调度产品。在本书中,我们不打算花功夫去了解和评估那些商业化产品。表1.1 中列出了当下流行的几个解决方案,你可以通过所给相应的URL获得更详尽的信息。

表 1.1 商业作业调度器
名称网址
Flux Schedulerwww.fluxcorp.com/
Enterprise Batching Queuingwww.argent.com/p/qe/qe.html
Unicenter AutoSys Job Management 4.5www.ca.com
BMC Software ControlMwww.bmc.com
Cybermation ESP Espresso 4.2www.cybermation.corly;9'm
Vexus consulting Avatar Job Scheduling Suite 4.5.5www.vexus.ca
Argent software The Argent Job Scheduler 4.5Awww.argent.com
Tidal Enterprise Schedulerwww.tidalsoftware.com



[版权声明]
本站内文章,如未特别注明,均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。
posted on 2007-10-17 02:17 隔叶黄莺 阅读(4840) 评论(14)  编辑  收藏 所属分类: Quartz

Feedback

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-17 09:23 paul
在项目中使用quartz作为作业调度框架,但现在 有个问题一直未解决,就是在执行了一段时间后,就不再执行了,通过命令查看进程仍在,也无异常信息,好像进程死在哪里了,不知什么原因?
我的msn:e3002@163.com  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2007-10-17 10:02 Unmi
Quartz建议总是放一个自己的quartz.properties文件在classpath下,运行时可覆盖quartz.jar中的quartz.properties的配置,因为根据自己实际的应用,需要对quartz配置作些调整。

对于楼上的问题,不妨在quartz.propertiesr根据你的作业数量与频度把
org.quartz.threadPool.threadCount
设置大一些,同时启动更多的线程来处理作业执行,默认值为5  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-18 12:58 paul
谢谢你的回复!
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
以上是quartz.property中的初始配置,以下是我的程序中的代码,应该设置了线程池的线程数为20,那么默认的那个应该没作用了吧,现在线程池是20,按楼上的说法,我应该 把这个设置大些吗?
ThreadPool tp = ThreadPool.createThreadPool(false);
tp.setMaxThreads(20);
tp.setMaxSpareThreads(10);
tp.setMinSpareThreads(5);
tp.start();  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2007-10-18 23:31 Unmi
完成了第一章,乐意接受大家的珠矶之言,狠批也高兴  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-19 09:52 paul
楼主等着你回答我的问题那,哈哈!  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2007-10-19 10:01 Unmi
调试状态可以看看,调度器一启动后,会同时带动多少个线程来就知道是哪个配置起作用了  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-23 17:10 paul
请问org.quartz.jobStore.misfireThreshold = 60000中的这个词misfireThreshold该怎么翻译啊,是什么意思?这是设置什么属性???  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2007-10-23 20:59 Unmi
没法直接翻译,大致意思是 当前时超过已安排时间多久的作业不执行

比如说设置了一个工作线程,安排作业是一秒执行一次,作业本身执行10秒
如果
org.quartz.jobStore.misfireThreshold = 60000 #60秒

那么执行第一次作业是在10:01秒,这时会设定下一次的执行时间为10:02秒,要等一个作业执行完之后才有可用线程,大概要在10:11秒才能执行前面安排的应该在10:02执行的作业,这时就会用到misfireThreshold, 因为10:11与10:02之间的差值小于6000,所以执行该作业,并以10:02为基准设置下一次执行时间为10:03,这样造成每次实际执行时间与安排时间错位

如果
org.quartz.jobStore.misfireThreshold = 6000 #秒
同样,在10:11计划执行安排在10:02的作业,发现10:11与10:02之间的差值小于6000,那么直接跳过该作业,执行本应在当前时间执行的作业,这时候会以10:11为基准设定下次作业执行时间为10:12

不知道这样能不能理解清楚,有时候要保证执行次数,值就可以大一些;有些时候避免更多机会交替执行同一个作业就应该设置小一些。

有一个程序跑出来输出,作业执行代码如下:

DateFormat df = new SimpleDateFormat("hh:mm:ss");
System.err.println("["+Thread.currentThread().getName()+"] Now: "+df.format(context.getFireTime())
+" Scheduled: "+df.format(context.getScheduledFireTime())
+" Previous: "+df.format(context.getPreviousFireTime())
+" Next: "+df.format(context.getNextFireTime()));
try {
Thread.sleep(10*1000);
System.out.println("["+Thread.currentThread().getName()+"] Slept 10 seconds");
} catch (InterruptedException e) {
e.printStackTrace();
}

预设的工作线程为1,执行任务时间10秒misfireThreshold为6000时输出结果为:
[UnmiQuartzScheduler_Worker-1] Now: 08:26:20 Scheduled: 08:26:20 Previous: 08:26:10 Next: 08:26:21
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:26:30 Scheduled: 08:26:30 Previous: 08:26:20 Next: 08:26:31
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:26:40 Scheduled: 08:26:40 Previous: 08:26:30 Next: 08:26:41
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:26:50 Scheduled: 08:26:50 Previous: 08:26:40 Next: 08:26:51
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:27:00 Scheduled: 08:27:00 Previous: 08:26:50 Next: 08:27:01

预设的工作线程为1,执行任务时间10秒misfireThreshold为60000时输出结果为:
[UnmiQuartzScheduler_Worker-1] Now: 08:28:23 Scheduled: 08:27:47 Previous: 08:27:46 Next: 08:27:48
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:28:33 Scheduled: 08:27:48 Previous: 08:27:47 Next: 08:27:49
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:28:43 Scheduled: 08:27:49 Previous: 08:27:48 Next: 08:27:50
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:28:53 Scheduled: 08:28:53 Previous: 08:27:49 Next: 08:28:54
[UnmiQuartzScheduler_Worker-1] Slept 10 seconds
[UnmiQuartzScheduler_Worker-1] Now: 08:29:03 Scheduled: 08:28:54 Previous: 08:28:53 Next: 08:28:55  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-24 10:36 paul
谢谢楼主了!我想我的问题应该可以得到解决了,原因分析如下:
我的作业执行需要的时间较与任务的间隔时间相比小于其默认值60000ms了,所以一直没有线程释放!所以可以调小一些这个值!  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度[未登录] 2007-10-24 10:47 paul
或者可以改变任务执行的间隔时间  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2007-10-24 12:02 Unmi
设置合理的间隔时间是比较妥当的,应该事先可以大概知道每个作业的执行时间。  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2008-04-28 16:25 jacai
学习学习!  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2008-06-25 13:56 王世杰
无私奉献啊
太有才呢你
好好学一下  回复  更多评论
  

# re: Quartz Job Scheduling Framework[翻译]第一章. 企业应用中的作业调度 2008-07-21 12:18 隔叶黄莺
为何呢?本该删了你的评论,留在这里极不协调(不想讲和谐,和谐是个大谎言),干嘛要和人民作对?四川不是索多玛!  回复  更多评论
  



标题  
姓名  
主页
验证码 *  
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-08-21 23:11 编辑过