淘宝官方参考手册:http://code.taobao.org/p/tbschedule/wiki/index/
http://www.jianshu.com/p/e66aa342f0d1
1.TBSchedule项目其实可以分为两部分:
①TBSchedule管理控制台。负责监控,监控任务执行状态
②实际执行job的客户端程序
在实际使用时,首先要启动zookeeper,然后部署TBSchedule web界面的管理控制台,最后启动实际执行job的客户机器。这里zookeeper并不实际控制任务调度,它只是负责与N台执行job的客户端通讯,协调,管理,监控这些机器的运行信息。司机分配任务的是TBSchedule管理控制台,控制台从zookeeper获取job的运行信息。
TBSchedule通过控制ZNode的创建,修改,删除来间接控制Job的执行,执行Job的客户端会监听他们对应ZNode的状态更新事件,从而达到通过 TBSchedule控制Job执行的目的。
一,部署zookeeper(在这里为了简单安装的单机模式 ,集群模式参考我的另外一篇博客)
下载地址:http://zookeeper.apache.org/releases.html#download,在此我下载的是zookeeper-3.3.6.tar.gz 。
1.下载完成后解压到/application/software目录下面
2.建立软连接ln -s /application/software/zookeeper-3.3.6 /opt/zookeeker
3.将 /conf目录下的zoo_sample.cfg更名为zoo.cfg,因为zookeeper启动时会在这个目录下找zoo.cfg读取配置信息。这个文件里有几个重要的参数需要说明一下:
tickTime=2000
定义时间计量单位。这里表示一个tick为2秒。以后在配置时间相关的东西时,都是以tick为单位的。
dataDir=/opt/zookeer/data
定义快照(snapshot)文件的存储位置。zookeeper会将节点信息定时写入到这个目录中。这个目录必须存在,否则启动时会报错。
clientPort=2181
指定客户端连接端口。 zookeeper会在这个端口监听连接请求。
server.1=127.0.0.1:2000:3000
这个参数仅在集群部署时起作用。格式为:server.id=host:port:port。id表示服务器的唯一标识,一般从1开始计数。第一个port表示zookeeper集群机器之间的通讯端口,第二个port表示当集群机器在选举leader时使用的通讯端口。只有当集群第一次启动,或master机崩溃时,才会进行leader选举。
4.配置完成后,切换到/bin目录,执行:./zkServer.sh start
即可启动zookeeper,默认会在后台运行,如果想在前端运行,需要执行:./zkServer.sh start-foreground
注意:Zookeeper所在的linux服务器与TBSchedule客户端代码所在的机器时间要一致,简单起见可以使用linux命令设置时间日期
二,部署ScheduleConsole
下载地址:http://code.taobao.org/p/tbschedule/wiki/index/ ,在此我直接下载的ScheduleConsole.war
ScheduleConsole就是个用servlet/JSP写的web项目,我们可以把下载下来的ScheduleConsole.war直接发布到tomcat服务器上,然后在浏览器访问:
http://localhost:8080/ScheduleConsole
即可。
第一次访问控制台时会出现以下配置页面:
第一行指定zookeeper的地址、端口
第二行是超时时间。用户名和密码在这里没有任何用处,无视即可。
第三行Zookeeper的根目录,并不是指zookeeper所在的centos系统的某个目录,而是zookeeper的目录节点znode,TBSchedule管理控制台会将任务的配置信息(如执行开始时间,调度策略)保存到该目录下,这样下次启动管理控制台时就可以直接从目录中读取配置信息了。
填写完成后点保存。再点击管理主页即可进入管理页面,创建调度策略:
至此TBSchedule控制台部署完毕。
TBSchedule客户端编写
项目架构
springBoot + TBSchedule 实现任务调度
项目结构
项目搭建
1.pom.xml配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>springboot_tbschedule_demo</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.6.RELEASE</version> </parent> <dependencies> <!-- add typical dependencies for a web application --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.taobao.pamirs.schedule</groupId> <artifactId>tbschedule</artifactId> <version>3.2.14</version> </dependency> <!-- 使用log4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- 添加zookeeper依赖 --> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.3.6</version> </dependency> <!-- 依赖 --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.7</version> </dependency> </dependencies> <build> <plugins> <!-- Spring Boot提供了一个用于创建可执行jars的Maven插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <dependencies> <!-- 在我们开发过程中,我们需要经常修改,为了避免重复启动项目,我们可以启用热部署 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.5.RELEASE</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>
2.application.yml配置
logging: level: root: INFO job: zkConfig: zkConnectString: 10.10.28.111:2181 #注册中心地址 rootPath: /tb-schedule/dev #定时任务根目录,任意指定,调度控制台配置时对应 zkSessionTimeout: 60000 #超时配置 userName: admin #账户,任意指定,调度控制台配置时对应 password: admin #密码,任意指定,调度控制台配置时对应 isCheckParentPath: true
2.配置TBSchedule连接到zookeeper
package com.zto.demo.config; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.taobao.pamirs.schedule.strategy.TBScheduleManagerFactory; @Configuration public class TBScheduleJobConfig { /** *创建好Bean之后调用TBScheduleManagerFactory的初始化方法init()来进行初始化 */ @Bean(initMethod="init") public TBScheduleManagerFactory tbScheduleManagerFactory( @Value("${job.zkConfig.zkConnectString}")String zkConnectString, @Value("${job.zkConfig.rootPath}")String rootPath, @Value("${job.zkConfig.zkSessionTimeout}")String zkSessionTimeout, @Value("${job.zkConfig.userName}")String userName, @Value("${job.zkConfig.password}")String password, @Value("${job.zkConfig.isCheckParentPath}")String isCheckParentPath){ TBScheduleManagerFactory tbScheduleManagerFactory = new TBScheduleManagerFactory(); Map<String, String> zkConfig = new HashMap<String, String>(); zkConfig.put("zkConnectString", zkConnectString); zkConfig.put("rootPath", rootPath); zkConfig.put("zkSessionTimeout", zkSessionTimeout); zkConfig.put("userName", userName); zkConfig.put("password", password); System.out.println("userName:"+userName+", password:"+password); zkConfig.put("isCheckParentPath", isCheckParentPath); tbScheduleManagerFactory.setZkConfig(zkConfig); return tbScheduleManagerFactory; } }
3.任务实体类定义
package com.zto.demo.schedule.model; public class TaskModel { private String name; private String job; public TaskModel(String name, String job){ this.name = name; this.job = job; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } }
4.任务处理类定义
package com.zto.demo.schedule.task; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.taobao.pamirs.schedule.IScheduleTaskDealSingle; import com.taobao.pamirs.schedule.TaskItemDefine; import com.zto.demo.schedule.model.TaskModel; @Component("dataSyncABean") public class DataSyncABean implements IScheduleTaskDealSingle<TaskModel>{ private static final Logger LOG = Logger.getLogger(DataSyncABean.class); @Override public Comparator<TaskModel> getComparator() { // TODO Auto-generated method stub return null; } @Override public List<TaskModel> selectTasks(String taskParameter, String ownSign, int taskQueueNum, List<TaskItemDefine> taskItemList, int eachFetchDataNum) throws Exception { LOG.info("IScheduleTaskDealSingleTest配置的参数,taskParameter:"+taskParameter +",ownSign:"+ownSign +",taskQueueNum:"+taskQueueNum +",taskItemList:"+taskItemList +", eachFetchDataNum:"+eachFetchDataNum ); LOG.info(""); List<TaskModel> modelList = new ArrayList<TaskModel>(); modelList.add(new TaskModel(String.valueOf(System.currentTimeMillis()), "test1")); modelList.add(new TaskModel(String.valueOf(System.currentTimeMillis()), "test2")); return modelList; } @Override public boolean execute(TaskModel model, String ownSign) throws Exception { System.out.println(model.getJob()+" ************************ "+model.getName()); return true; } }
tbSchedule的调用流程为:
①执行selectTasks()方法,该方法返回一个List对象,表示你选择出的任务列表。
②执行execute()方法,tbschedule会遍历你在selectTasks()方法中返回的List,然后对每一个元素都调用execute()方法。
5.最后在Application中启动即可
package com.zto.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * * * 我们的Example类上使用的第一个注解是@RestController。这被称为一个构造型注解。它为阅读代码的人们提供建议。 * 对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web @Controller,所以当处理进来的web请求时, * Spring会询问他 * */ @SpringBootApplication public class Application{ public static void main(String[] args) throws Exception{ SpringApplication.run(Application.class, args); } }
任务调度的配置
进入TBSchedule管理控制台,创建一个新任务:
参考:http://blog.csdn.net/yuchao2015/article/details/53033628