分布式系统中的定时任务全解(一)
2016-06-11 19:23
323 查看
概述
分布式系统中的定时任务全解(二)–常见工程实现分布式系统中的定时任务全解(三)–ej实现
分布式系统中的定时任务全解(四)–补充
在网站系统里面定时任务是一个重要和不可缺的角色,很多地方需要使用定时执行一项任务。比如,订单系统的接单超时、支付超时,结算系统的定时结算、奖励计算,第三方的认证信息刷新(微信的token),dsp等推广平台数据定时对接,缓存数据的定时更新等。
定时任务实现方式
Timmer定时器
这时最简单和最基础的了,学习过计算机课程的都能知道也都能写。虽然常见,这里也简单的说几个点:
触发时间点
Timmer有两种指定执行时间的方式,一种是给一个时间间隔(Interval),另一种就是给定一个具体的执行时间。这时,timer的所有方法,其中画红圈圈的。第一个是在指定的时间点触发,给的参数是一个Date类型;第二个是按照指定的时间间隔触发,给的参数是一个long类型。这两种在实际工程中都是会被用到的。
Timer和TimerTask之间的关系
先看一个最常见的Timer使用示例:public class MyTimeTask { public static void main(String[] args){ Timer timer = new Timer(); timer.schedule(new MyTask1(), 60 * 1000); timer.schedule(new MyTask2(), 120 * 1000); } class MyTask1 extends TimerTask { public void run(){ System.out.println("running1...."); } } class MyTask2 extends TimerTask { public void run(){ System.out.println("running2...."); } } }
可以看到,一个Timer是可以调度多个Task的,这个也可以从Timer的源代码看出来:
mainloop循环在不断的读取queue中的task,逐个执行。对于按间隔期不断执行的task,会被计算下次执行时间后被重新放入到队列中。
这里的queue是一个优先级队列,会按照task的执行时间排序,最近的task会被先取出来执行。
这里想说的是什么呢,在工程中最好不要一个task就创建一个timer,这样有点过于浪费系统资源,因为一个timer就是一个线程,而且在不断的消耗系统的cpu资源。
quartz
quartz是java里面最流行的定时任务调度框架,python里面的定时任务框架APScheduler也是基于Quartz,实现了Quartz的所有功能。这里把quartz的内容多介绍一些,因为后续集群部分涉及到的elastic-job,同样是基于quartz实现的。要了解更多关于quartz的只是,推荐两个网站:
官网教程目录页
http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/
以梦为马的个人博客(一个系列的3篇)
http://blog.csdn.net/ahmuamu/article/details/50364769
quartz的只要构成是schedule、trigger、job三元素的体系,体系中还提供了三者各自的Listener用来监听他们的事件和对事件作出响应。以下是一个最原始的、最基础的quartz使用示例代码(来自官网):
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory(); Scheduler sched = schedFact.getScheduler(); sched.start(); // define the job and tie it to our HelloJob class JobDetail job = newJob(HelloJob.class) .withIdentity("myJob", "group1") .build(); // Trigger the job to run now, and then every 40 seconds Trigger trigger = newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(simpleSchedule() .withIntervalInSeconds(40) .repeatForever()) .build(); // Tell quartz to schedule the job using our trigger sched.scheduleJob(job, trigger);
贴在这里,是为了让大家理解三者之间的关系。job封装任务执行的代码,trigger封装任务执行的时间信息,schedule绑定job和trigger执行任务调度。
在java世界里,spring已经是无所不在,接下来简单的看一下spring集成quartz需要做的事情(理解的上述的代码,也就容易理解,为什么spring配置文件里要配置这些东西了)。
1.首先就是要把quartz的包引入进来,添加maven引用:
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>${quartz.version}</version> </dependency>
2.定义job,定义job有两种方式,一种是使用MethodInvokingJobDetailFactoryBean封装自己的bean,这样自己的bean可以是一个任意的pojo;第二种是使用JobDetailFactoryBean,同时让自己的job扩展QuartzJobBean,实现executeInternal的抽象方法。
具体可以参加(这里给的比较详细):http://websystique.com/spring/spring-4-quartz-scheduler-integration-example/
3.定义trigger
这里可以定义简单的trigger(SimpleTriggerFactoryBean),他使用的是jdk的timer做为调度;也可以定义一个cron表达式类型的trigger(CronTriggerFactoryBean)去定义一个更语义化的触发表达式。
关于cron表达式的知识,可以参见这里:http://www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-06.html
4.定义scheduler,绑定trigger和job
spring-scheduled注解
spring自己也提供了一个轻量级的定时任务工具,而且是在core包里面。可以使用scheduled注解,也可以仅使用xml配置。虽然说它轻量级,但是他实现了quartz支持的两种时间触发机制,简单的和cron表达式的。说他轻量级,也是因为他不能支持quartz能够支持的集群功能。这里先推荐一个spring的官方版本(如果对spring-scheduled没有概念,需要先查baidu了解一些之后再看这里,因为这个写的比较简洁):http://spring.io/guides/gs/scheduling-tasks/
接下来一块看下scheduled的注解使用,也是两种用法,一个是普通的timer类似调度,一种是cron表达式方式调度。
这里只看cron表达是方式的,普通方式的请见上述网址。以下示例来自于http://howtodoinjava.com/。关于spring-scheduled的使用推荐以下几个网址:
http://howtodoinjava.com/spring/spring-core/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/
http://www.cnblogs.com/Gyoung/p/5339242.html
http://spring.io/guides/gs/scheduling-tasks/
1.引入task命名空间,开启注解自动识别
< ?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util/ http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <task:annotation-driven /> </beans>
2.在需要调度的方法上添加@scheduled注解
@Scheduled(fixedDelay =30000) public void demoServiceMethod () {... } @Scheduled(fixedRate=30000) public void demoServiceMethod () {... } @Scheduled(cron="0 0 * * * *") public void demoServiceMethod () {... }
好了看今天先说到这里,下一篇整理一下quartz基于数据库的集群实现以及elastic-job的使用。最后在给出一篇elastic-job的解析,以及从解析看实际使用场景的实现。
相关文章推荐
- 分布式版本管理git入门指南使用资料汇总及文章推荐
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- ruby中执行周期性任务(定时任务)的3种方法
- C#分布式事务的超时处理实例分析
- 使用mysql事件调度器定时删除binlog
- Erlang分布式节点中的注册进程使用实例
- ASP中实现执行定时任务的方法
- 调试WordPress中定时任务的相关PHP脚本示例
- java定时任务的实现方式
- node.js中使用node-schedule实现定时任务实例
- 详解PHP实现执行定时任务
- php定时计划任务的实现方法详解
- PHP定时执行任务的3种方法详解
- 详解PHP执行定时任务的实现思路
- C++实现的分布式游戏服务端引擎KBEngine详解
- 在WordPress中使用wp-cron插件来设置定时任务
- Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
- PHP中使用sleep函数实现定时任务实例分享
- yii框架通过控制台命令创建定时任务示例