您的位置:首页 > 编程语言 > Java开发

Spring Task定时任务

2016-05-17 00:00 501 查看
Spring Task定时任务
1.基于Spring Task的任务调度方法:
Spring框架自带的异步执行(TaskExecutor)和任务调度(TaskScheduler)接口。
Spring Task官方地址:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
以下是task任务调度配置:spring-tasks.xml

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
default-lazy-init="false">

<context:annotation-config />
<!--  spring扫描注解的配置   -->
<context:component-scan base-package="com.ouc.test.task" />

<!--开启这个配置,spring才能识别@Scheduled注解   -->
<task:annotation-driven scheduler="testScheduler" mode="proxy"/>
<task:scheduler id="testScheduler" pool-size="10"/>
<task:scheduled-tasks> </task:scheduled-tasks>

</beans>


任务调度具体实现:TestTask.java

package com.ouc.test.task;

import java.text.SimpleDateFormat;;
import java.util.Calendar;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component("TestTask")
public class TestTask {

//每天凌晨4:40执行
@Scheduled(cron = "0 40 4 * * ?")
public void TestTask() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date factInPlaceDate = new Date();

Calendar beforeCd = Calendar.getInstance();
beforeCd.setTime(factInPlaceDate);
beforeCd.add(Calendar.MONTH, -1);
Date beforeFactDate = beforeCd.getTime();
String beforeMonthDate = sdf.format(beforeFactDate);
System.out.println("实际到位日期减一个月:" + beforeMonthDate);

Calendar afterCd = Calendar.getInstance();
afterCd.setTime(factInPlaceDate);
afterCd.add(Calendar.MONTH, +1);
Date afterFactDate = afterCd.getTime();
String afterMonthDate = sdf.format(afterFactDate);
System.out.println("实际到位日期加一个月:" + afterMonthDate);
}
}


Spring定时任务cronExpression的值(配置定时时间)格式说明:
一个cronExpression表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下:

(1) 秒(0–59) , - * /

(2)分钟(0–59), - * /

(3)小时(0–23) , - * /

(4)月份中的日期(1–31) , - * ? / L W C

(5)月份(1–12或JAN–DEC) , - * /

(6)星期中的日期(1–7或SUN–SAT) , - * ? / L C #

(7)年份(1970–2099) (可选) 留空, - * /
表达式意义 :
"0 0 12 * * ?" 每天中午12点触发
"0 30 9 ? * *" 每天上午9:30触发
"0 30 9 * * ? 2008" 2008年的每天上午9:30触发
"0 * 13 * * ?" 在每天下午1点到下午1:59期间的每1分钟触发
"0 0/5 13 * * ?" 在每天下午1点到下午1:55期间的每5分钟触发
"0 0/5 13,18 * * ?" 在每天下午1点到2:55期间和下午6点到6:55期间的每5分钟触发
"0 0-5 12 * * ?" 在每天下午1点到下午1:05期间的每1分钟触发
"0 10,50 14 ? 3 WED" 每年三月的星期三的下午2:10和2:50触发
"0 30 10 ? * MON-FRI" 周一至周五的上午10:30触发
"0 30 10 15 * ?" 每月15日上午10:30触发
"0 30 10 L * ?" 每月最后一日的上午10:30触发
"0 30 10 ? * 6L" 每月的最后一个星期五上午10:30触发
"0 30 10 ? * 6L 2006-2008" 2006年至2008年的每月的最后一个星期五上午10:30触发
"0 15 9 ? * 6#3" 每月的第三个星期五上午9:15触发
"0 5 * * * " 每天早上5点触发
"0 */2 * * * " 每两小时触发
"0 23-6/2,7 * * * " 晚上11点到早上6点之间每两个小时,早上7点触发
"0 5 1 * 1-3"每个月的4号和每个礼拜的礼拜一到礼拜三的早上5点触发
"0 2 1 1 * " 1月1日凌晨2点触发

「?」字符:表示不确定的值
「,」字符:指定数个值
「-」字符:指定一个值的范围
「/」字符:指定一个值的增加幅度。n/m 表示从 n 开始,每次增加 m
「L」字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期 X
「W」字符:指定离给定日期最近的工作日 (周一到周五)
「#」字符:表示该月第几个周 X。6#3 表示该月第 3 个周五

2.基于定时器Timer的定时任务:
TimerManager.java

package com.ouc.test.main;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;

public class TimerManager {

public static void main(String[] args) {
// TODO Auto-generated method stub
new TimerManager();
}
private static final long PERIOD_DAY = 24 * 60 * 60 * 1000; //一天
//private static final long PERIOD_WEEK = 7 * 24 * 60 * 60 * 1000; //一周
public TimerManager(){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 18);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date date=calendar.getTime(); //第一次执行定时任务的时间
//如果第一次执行定时任务的时间 小于当前的时间
//此时要在 第一次执行定时任务的时间加一天,以便此任务在下个时间点执行。如果不加一天,任务会立即执行。
if (date.before(new Date())) {
date = this.addDay(date, 1);
}
Timer timer = new Timer();
System.out.println(date);//输出开始日期
OrderTask orderTask = new OrderTask();
//安排指定的任务在指定的时间开始进行重复的固定延迟执行。

timer.schedule(orderTask, date, PERIOD_DAY);//订单

}
//增加或减少天数
public Date addDay(Date date, int num) {
Calendar startDT = Calendar.getInstance();
startDT.setTime(date);
startDT.add(Calendar.DAY_OF_MONTH, num);
return startDT.getTime();
}
}


OrderTask.java

package com.ouc.test.main;

import java.util.TimerTask;

public class OrderTask extends TimerTask {

public static void main(String[] args) {
// TODO Auto-generated method stub
OrderTask orerTask = new OrderTask();
orerTask.run();
}

public void run() {
getOrderInfo();
}

public void getOrderInfo() {
System.out.println("正在测试Timer定时任务!");
}
}




3.Quartz任务调度框架

4.LTS轻任务调度框架介绍:

• LTS框架概况:
LTS是一个轻任务调度框架,参考hadoop的部分思想。有三种角色, JobClient, JobTracker,TaskTracker。各个节点都是无状态的,可以部署多个,来实现负载均衡,实现更大的负载量, 并且框架具有很好的容错能力。 采用Zookeeper暴露节点信息,master选举。Mongo存储任务队列和任务执行日志, netty做底层通信。
▶ JobClient : 主要负责提交任务, 和接收任务执行反馈结果。
▶ JobTracker : 负责接收并分配任务,任务调度。
▶ TaskTracker: 负责执行任务,执行完反馈给JobTracker。
• 架构图:



• 节点组:
▶ 一个节点组等同于一个集群,同一个节点组中的各个节点是对等的,外界无论连接节点组中的任务一个节点都是可以的。
▶ 每个节点组中都有一个master节点,采用zookeeper进行master选举(master宕机,会自动选举出新的master节点),框架会提供接口API来监听master节点的变化,用户可以自己使用master节点做自己想做的事情。
▶ JobClient和TaskTracker都可以存在多个节点组。譬如JobClient 可以存在多个节点组。譬如:JobClient 节点组为‘QN_WEB’中的一个节点提交提交一个只有节点组为‘QN_TRADE’的TaskTracker 才能执行的任务。
▶ (每个集群中)JobTacker只有一个节点组。
▶ 多个JobClient节点组和多个TaskTracker节点组再加上一个JobTacker节点组, 组成一个大的集群。

• 工作流程:
▶ JobClient提交一个任务给 JobTracker, 这里我提供了两种客户端API, 一种是如果JobTracker 不存在或者提交失败,直接返回提交失败。另一种客户端是重试客户端, 如果提交失败,先存储文件,返回给客户端提交成功的信息,待JobTracker可用的时候,再将任务提交。
▶ JobTracker收到JobClient提交来的任务,先生成一个唯一的JobID。然后将任务储存在Mongo集群中。JobTracker 发现有(任务执行的)可用的TaskTracker节点(组)之后,将优先级最大,最先提交的任务分发给TaskTracker。这里JobTracker会优先分配给比较空闲的TaskTracker节点,达到负载均衡。
▶ TaskTracker收到JobTracker分发来的任务之后,执行。执行完毕之后,再反馈任务执行结果给JobTracker(成功or 失败[失败有失败错误信息]),如果发现JobTacker不可用,那么存储文件,等待TaskTracker可用的时候再反馈。反馈结果的同时,询问 JobTacker有没有新的任务要执行。
▶ JobTacker收到TaskTracker节点的任务结果信息,生成并插入(mongo)任务执行日志。根据任务信息决定要不要反馈给客户端。不需要反馈的直接删除, 需要反馈的(同样JobClient不可用存储文件,等待可用重发)。
▶ JobClient收到任务执行结果,进行自己想要的逻辑处理。

• 特性
▶ 负载均衡:
▷ JobClient和 TaskTracker会随机连接JobTracker节点组中的一个节点,实现JobTracker负载均衡。当连接上后,将一直保持连接这个节点,保持连接通道,知道这个节点不可用,减少每次都重新连接一个节点带来的性能开销。
▷ JobTracker分发任务时,是优先分配给最空间的一个TaskTracker节点,实现TaskTracker节点的负载均衡。
▶ 健壮性:
▷ 当节点组中的一个节点当机之后,自动转到其他节点工作。当整个节点组当机之后,将会采用存储文件的方式,待节点组可用的时候进行重发。
▷ 当执行任务的TaskTracker节点当机之后,JobTracker会将这个TaskTracker上的未完成的任务(死任务),重新分配给节点组中其他节点执行。
▶ 伸缩性:
因为各个节点都是无状态的,可以动态增加机器部署实例, 节点关注者会自动发现。

• 调用示例
安装 zookeeper 和 mongo , 执行 data/mongo目录下的 mongo.md 中的语句见 job-example 这里给出的是java API(设置配置)方式启动,也可以使用配置文件中。
▶ JobTracker端



▶ JobClient端



▶ TaskTracker端

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: