项目作者: tianzi94wob

项目描述 :
基于zookeeper+quartz的分布式任务调度组件
高级语言: Java
项目地址: git://github.com/tianzi94wob/task-schedule.git
创建时间: 2017-03-03T05:19:18Z
项目社区:https://github.com/tianzi94wob/task-schedule

开源协议:

下载


task-schedule

基于zookeeper+quartz的分布式任务调度组件,非常小巧,使用简单,只需要引入jar包,不需要单独部署服务端。确保所有任务在集群中均匀分布,不重复,不遗漏的执行。
支持动态添加和删除任务。

功能概述

  1. 基于zookeeper+quartz的分布任务调度系统,适合多任务的系统使用,合理分配资源。
  2. 确保每个任务在集群节点均匀分布,不重复不遗漏的执行。
  3. 单个任务节点故障时自动转移到其他任务节点继续执行。
  4. 任务节点启动时必须保证zookeeper可用,任务节点运行期zookeeper集群不可用时任务节点保持可用前状态运行,zookeeper集群恢复正常运期。
  5. 添加ip黑名单,过滤不需要执行任务的节点。
  6. 提供简单管理页面、任务管理的接口。
  7. 任务持久化。

模块架构

image

image

image

管理页面

image

访问URL:项目名称/taskSchedule/index,如果servlet3.x以下,请手动配置web.xml文件

  1. <servlet>
  2. <servlet-name>TaskSchedule</servlet-name>
  3. <servlet-class>com.secsbrain.frame.task.web.HomeServlet</servlet-class>
  4. </servlet>
  5. <servlet-mapping>
  6. <servlet-name>TaskSchedule</servlet-name>
  7. <url-pattern>/taskSchedule/*</url-pattern>
  8. </servlet-mapping>

任务持久化脚本

  1. -- ----------------------------
  2. -- Table structure for `sys_task_schedule_job`
  3. -- ----------------------------
  4. DROP TABLE IF EXISTS `sys_task_schedule_job`;
  5. CREATE TABLE `sys_task_schedule_job` (
  6. `id` int(11) NOT NULL AUTO_INCREMENT,
  7. `job_name` varchar(255) DEFAULT NULL COMMENT '任务名称',
  8. `job_status` varchar(1) DEFAULT NULL COMMENT '任务状态 0-停止,1-运行,2-删除',
  9. `job_group` varchar(255) NOT NULL COMMENT '任务组',
  10. `cron_expression` varchar(255) DEFAULT NULL COMMENT '表达式',
  11. `bean_class` varchar(255) DEFAULT NULL COMMENT '类路径',
  12. `spring_id` varchar(255) DEFAULT NULL COMMENT 'springId',
  13. `method_name` varchar(255) DEFAULT NULL COMMENT '方法名',
  14. `is_concurrent` varchar(1) DEFAULT NULL COMMENT '是否同步',
  15. `description` varchar(500) DEFAULT NULL COMMENT '描述',
  16. `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  17. `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  18. `prj_name` varchar(50) DEFAULT NULL COMMENT '工程名,与需要调度任务的工程名保持一致,如果部署在根目录则为空',
  19. PRIMARY KEY (`id`)
  20. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务调度配置表';
  21. -- ----------------------------
  22. -- Records of sys_task_schedule_job
  23. -- ----------------------------
  24. INSERT INTO `sys_task_schedule_job` VALUES ('12', 'job-test', '1', 'test', '0 0/10 * * * ?',
  25. 'com.secsbrain.live.mgr.job', '', 'gogogo', '1', '任务测试', '2017-01-10 17:05:06', '2017-01-12 17:07:34', 'live-mgr');
  26. ###如果应用的上下文没有子路径,就是直接通过ip:port访问。那么prj_name填BLANK,这样一来只支持一个应用了。

新建类,用于测试JOB:

  1. package com.secsbrain.live.mgr.job;
  2. /**
  3. * 任务测试类
  4. *
  5. * @author zhaoyi
  6. */
  7. public class JobTest {
  8. public void gogogo(){
  9. System.out.println("如果觉得快乐你就拍拍手");
  10. }
  11. }

zookeeper需3.4.8以上版本

传统spring配置

  1. <!-- 扫描路径 -->
  2. <context:component-scan base-package="com.secsbrain.frame.task"></context:component-scan>
  3. <!-- 数据源注入 -->
  4. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  5. <property name="dataSource" ref="dataSource"></property>
  6. </bean>
  7. <!-- 定时任务管理类 -->
  8. <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  9. <property name="quartzProperties">
  10. <props>
  11. <prop key="org.quartz.scheduler.skipUpdateCheck">true</prop>
  12. </props>
  13. </property>
  14. </bean>
  15. <!-- 分布式任务管理器-->
  16. <bean id="zkScheduleManager" class="com.secsbrain.frame.task.ZKScheduleManager" init-method="init">
  17. <property name="zkConfig">
  18. <map>
  19. <entry key="zkConnectString" value="127.0.0.1:2181" ></entry><!-- zk地址 -->
  20. <entry key="rootPath" value="/task1.0/schedule" ></entry><!-- 根目录,除非组件升级,尽量不要改动-->
  21. <entry key="zkSessionTimeout" value="60000" ></entry><!-- 连接超时时间 -->
  22. <entry key="userName" value="test" ></entry><!-- 自定义用户名 -->
  23. <entry key="password" value="test" ></entry><!-- 自定义密码 -->
  24. <entry key="ipBlacklist" value="127.0.0.2,127.0.0.3" ></entry><!-- 黑名单-->
  25. </map>
  26. </property>
  27. </bean>

springboot配置

  1. @Configuration
  2. public class TaskScheduleConfig {
  3. @Value("${zookeeper.address}")
  4. private String zookeeperUrl;
  5. @Bean(name = "zkScheduleManager",initMethod="init")
  6. public ZKScheduleManager zkScheduleManager(){
  7. ZKScheduleManager zkScheduleManager=new ZKScheduleManager();
  8. Map<String, String> zkConfig=new HashMap<>();
  9. zkConfig.put("zkConnectString", zookeeperUrl);
  10. zkConfig.put("rootPath", "/task_brain/schedule");
  11. zkConfig.put("zkSessionTimeout", "60000");
  12. zkConfig.put("userName", "test");
  13. zkConfig.put("password", "test");
  14. zkScheduleManager.setZkConfig(zkConfig);
  15. return zkScheduleManager;
  16. }
  17. @Bean(name = "schedulerFactoryBean")
  18. public SchedulerFactoryBean schedulerFactoryBean(){
  19. SchedulerFactoryBean schedulerFactoryBean=new SchedulerFactoryBean();
  20. Properties quartzProperties=new Properties();
  21. quartzProperties.put("org.quartz.scheduler.skipUpdateCheck", true);
  22. schedulerFactoryBean.setQuartzProperties(quartzProperties);
  23. return schedulerFactoryBean;
  24. }
  25. /**
  26. * 代码注册servlet(不需要@ServletComponentScan注解)
  27. * @return
  28. */
  29. @Bean
  30. public ServletRegistrationBean servletRegistrationBean() {
  31. return new ServletRegistrationBean(new HomeServlet(), "/taskSchedule/*");
  32. }
  33. }

注:如果觉得日志过多,可以屏蔽日志。

logback: <logger name="com.secsbrain.frame.task" level="info" ></logger>

log4j:log4j.logger.com.secsbrain.frame.task=info

还要把logback的隐式依赖给去掉:

  1. <dependency>
  2. <groupId>com.github.tianzi94wob</groupId>
  3. <artifactId>frame-task</artifactId>
  4. <version>1.0.0.RELEASES</version>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>ch.qos.logback</groupId>
  8. <artifactId>logback-classic</artifactId>
  9. </exclusion>
  10. <exclusion>
  11. <groupId>ch.qos.logback</groupId>
  12. <artifactId>logback-core</artifactId>
  13. </exclusion>
  14. </exclusions>
  15. </dependency>

1.0.0.RELEASES版本,包需要换成com.secsbrain

此外,zookeeper的版本需要3.4.6以上

API

  1. 动态设置任务
    1. ConsoleManager.setScheduleTask(TaskDefine taskDefine);
  2. 动态删除任务
    1. ConsoleManager.delScheduleTask(String targetBean, String targetMethod);
  3. 查询任务列表
    1. ConsoleManager.queryScheduleTask();

持久化任务管理

注入bean:TaskScheduleJobService

  1. 查询持久化任务列表

    1. List<TaskScheduleJob> queryTaskScheduleJobList(TaskScheduleJob taskScheduleJob);
  2. 添加持久化任务

    1. void addTask(TaskDefine taskDefine) throws Exception;
  3. 通过任务ID更新,工程名、表达式、任务描述

    1. void updateTask(TaskScheduleJob taskScheduleJob) throws Exception;
  4. 逻辑删除任务

    1. void deleteTask(Long jobId) throws Exception;
  5. 查看任务实际运行的详情

    1. TaskBean selectTaskDetail(Long jobId) throws Exception;
  6. 更改任务状态

    1. void changeStatus(Long jobId, String cmd) throws Exception;

用户按需使用接口开发持久化任务管理界面

前端工程地址:https://github.com/tianzi94wob/task-schedule-npm

不足

目前从新增任务到调度有1~2秒的延迟,请在实际业务场景开发中注意规避这个问题。如果zk迁移,需要注意把老数据也迁移过去

我的第一次开源尝试。反反复复修改了好几个月。这个组件应用场景目前还比较单一,可能还会存在一些问题,希望大家一起来优化这个组件,为开源社区作贡献!

大家都在用

关于

改进于uncode-schedule,作者:冶卫军(ywj_316@qq.com,微信:yeweijun)

作者:赵毅(531559024@qq.com