Spring Task定时任务

来源:互联网 发布:碧姬芭铎 知乎 编辑:程序博客网 时间:2024/05/21 11:01

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

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"      
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  4.     xmlns:task="http://www.springframework.org/schema/task"     
  5.     xmlns:context="http://www.springframework.org/schema/context"     
  6.     xsi:schemaLocation="      
  7.         http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd    
  8.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd    
  9.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd    
  10.         default-lazy-init="false">      
  11.   
  12.          <context:annotation-config />    
  13.         <!--  spring扫描注解的配置   -->    
  14.         <context:component-scan base-package="com.ouc.test.task" />  
  15.                 
  16.        <!--开启这个配置,spring才能识别@Scheduled注解   -->    
  17.        <task:annotation-driven scheduler="testScheduler" mode="proxy"/>    
  18.        <task:scheduler id="testScheduler" pool-size="10"/>    
  19.            <task:scheduled-tasks> </task:scheduled-tasks>  
  20.   
  21. </beans>  

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

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.ouc.test.task;  
  2.   
  3. import java.text.SimpleDateFormat;;  
  4. import java.util.Calendar;  
  5. import java.util.Date;  
  6.   
  7. import org.springframework.scheduling.annotation.Scheduled;  
  8. import org.springframework.stereotype.Component;  
  9.   
  10. @Component("TestTask")  
  11. public class TestTask {  
  12.       
  13.     //每天凌晨4:40执行  
  14.     @Scheduled(cron = "0 40 4 * * ?")  
  15.     public void TestTask() {  
  16.     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");    
  17.     Date factInPlaceDate = new Date();  
  18.   
  19.         Calendar beforeCd = Calendar.getInstance();    
  20.     beforeCd.setTime(factInPlaceDate);    
  21.     beforeCd.add(Calendar.MONTH, -1);    
  22.     Date beforeFactDate = beforeCd.getTime();   
  23.     String beforeMonthDate = sdf.format(beforeFactDate);  
  24.     System.out.println("实际到位日期减一个月:" + beforeMonthDate);  
  25.           
  26.     Calendar afterCd = Calendar.getInstance();    
  27.     afterCd.setTime(factInPlaceDate);    
  28.     afterCd.add(Calendar.MONTH, +1);    
  29.     Date afterFactDate = afterCd.getTime();   
  30.     String afterMonthDate = sdf.format(afterFactDate);  
  31.     System.out.println("实际到位日期加一个月:" + afterMonthDate);  
  32.    }    
  33. }  

      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

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.ouc.test.main;  
  2.   
  3. import java.util.Calendar;  
  4. import java.util.Date;  
  5. import java.util.Timer;  
  6.   
  7. public class TimerManager {  
  8.   
  9.     public static void main(String[] args) {  
  10.         // TODO Auto-generated method stub  
  11.          new TimerManager();  
  12.     }  
  13.     private static final long PERIOD_DAY = 24 * 60 * 60 * 1000//一天  
  14.     //private static final long PERIOD_WEEK = 7 * 24 * 60 * 60 * 1000; //一周  
  15.     public TimerManager(){  
  16.         Calendar calendar = Calendar.getInstance();  
  17.         calendar.set(Calendar.HOUR_OF_DAY, 18);  
  18.         calendar.set(Calendar.MINUTE, 0);  
  19.         calendar.set(Calendar.SECOND, 0);    
  20.         Date date=calendar.getTime(); //第一次执行定时任务的时间    
  21.         //如果第一次执行定时任务的时间 小于当前的时间    
  22.         //此时要在 第一次执行定时任务的时间加一天,以便此任务在下个时间点执行。如果不加一天,任务会立即执行。    
  23.         if (date.before(new Date())) {    
  24.             date = this.addDay(date, 1);    
  25.         }    
  26.         Timer timer = new Timer();    
  27.         System.out.println(date);//输出开始日期  
  28.         OrderTask orderTask = new OrderTask();    
  29.         //安排指定的任务在指定的时间开始进行重复的固定延迟执行。  
  30.          
  31.         timer.schedule(orderTask, date, PERIOD_DAY);//订单  
  32.   
  33.     }  
  34.     //增加或减少天数    
  35.     public Date addDay(Date date, int num) {    
  36.         Calendar startDT = Calendar.getInstance();    
  37.         startDT.setTime(date);    
  38.         startDT.add(Calendar.DAY_OF_MONTH, num);    
  39.         return startDT.getTime();    
  40.     }    
  41. }  

         OrderTask.java

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.ouc.test.main;  
  2.   
  3. import java.util.TimerTask;  
  4.   
  5. public class OrderTask extends TimerTask {  
  6.       
  7.     public static void main(String[] args) {  
  8.         // TODO Auto-generated method stub  
  9.             OrderTask orerTask = new OrderTask();  
  10.         orerTask.run();  
  11.     }  
  12.   
  13.     public void run() {  
  14.         getOrderInfo();  
  15.     }  
  16.   
  17.     public void getOrderInfo() {  
  18.           System.out.println("正在测试Timer定时任务!");  
  19.         }  
  20. }  

      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端

      

0 0
原创粉丝点击