elastic-job动态添加定时任务
在elastic-job的使用过程中,我们会遇到动态添加定时任务的时候,但是官网上面并没有对这块内容进行说明。按照我的理解以及官网上面elastic-job的框架图,ej的定时任务其实是存储在zookeeper的一个个节点上面,所以通过给zookeeper添加对应的节点即可完成定时任务的添加动作。
下面上代码:
import java.text.SimpleDateFormat;
import java.util.Date;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.exception.JobSystemException;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DynamicAddJob implements SimpleJob{
private static final String CRON_DATE_FORMAT = "ss mm HH dd MM ? yyyy";
/***
* @param date 时间
* @return cron类型的日期
*/
public static String getCron(final Date date) {
SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
String formatTimeStr = "";
if (date != null) {
formatTimeStr = sdf.format(date);
}
return formatTimeStr;
}
public static void main(String[] args){
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-job.xml");
ZookeeperRegistryCenter zookeeperRegistryCenter = context.getBean(ZookeeperRegistryCenter.class);
long now = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
String cron = getCron(new Date(now + (i + 1) * 50000));
JobCoreConfiguration coreConfig = JobCoreConfiguration.newBuilder("dynamicDemoJob-" + i, cron, 2).build();
SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(coreConfig, DynamicAddJob.class.getCanonicalName());
JobScheduler jobScheduler = new JobScheduler(zookeeperRegistryCenter, LiteJobConfiguration.newBuilder(simpleJobConfig).build());
try {
jobScheduler.init();
}catch (JobSystemException e){
e.printStackTrace();
}
}
}
@Override
public void execute(ShardingContext shardingContext) {
switch (shardingContext.getShardingItem()){
case 0:
System.out.println("doing sharding 0...job name is "+shardingContext.getJobName());
// do something by sharding item 0
break;
case 1:
System.out.println("doing sharding 1...job name is "+shardingContext.getJobName());
// do something by sharding item 1
break;
}
}
}
这里用到比较重要的一个类是JobScheduler,这是lite-core里面一个比较核心的类,这个类其实就是我们的job,他的构造方法包含以下参数:
- CoordinatorRegistryCenter regCenter:注册中心,这里是zookeeper
- LiteJobConfiguration liteJobConfig:定时任务的配置信息
这里可以看一下LiteJobConfiguration这个类,采用了设计模式中的建造者模式进行构建。可能看着会比较摸不着头脑,里面的Builder跟平时的不太一样,这里我们需要知道的是ej的源码采用了lombok这个代码简化的工具,只需要通过注解的形式就能将我们平时所需要的get/set和构造器的内容在编译时创建出来,不需要在代码中体现,能够大大简化我们的代码。
另外还遇到一个坑。这段代码不能重复使用,第一次跑的时候没问题,过段时间再次跑这个代码时,会在init()处报错,原因是我们新建的job根本不能被fire,我跟了进去。发现,job的cron表达式表示的时间还是以前的时间,这就奇怪了,明明我这边配置了一个新的时间。通过debug,进入init方法中,发现他会更新job信息,而更新时,会去zk上面load配置信息,而zk的znode节点是老的节点,上面存储的配置信息也是老的,所以这块的cron表达式也是旧的时间,根本不会被执行,下面贴出源码,供大家参考。
init()源码:
/**
* 初始化作业.
*/
public void init() {
LiteJobConfiguration liteJobConfigFromRegCenter = schedulerFacade.updateJobConfiguration(liteJobConfig);
JobRegistry.getInstance().setCurrentShardingTotalCount(liteJobConfigFromRegCenter.getJobName(), liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getShardingTotalCount());
JobScheduleController jobScheduleController = new JobScheduleController(createScheduler(), createJobDetail(liteJobConfigFromRegCenter.getTypeConfig().getJobClass()), liteJobConfigFromRegCenter.getJobName());
JobRegistry.getInstance().registerJob(liteJobConfigFromRegCenter.getJobName(), jobScheduleController, regCenter);
schedulerFacade.registerStartUpInfo(!liteJobConfigFromRegCenter.isDisabled());
jobScheduleController.scheduleJob(liteJobConfigFromRegCenter.getTypeConfig().getCoreConfig().getCron());
}
updateJobConfiguration()的源码如下:
/**
* 更新作业配置.
*
* @param liteJobConfig 作业配置
* @return 更新后的作业配置
*/
public LiteJobConfiguration updateJobConfiguration(final LiteJobConfiguration liteJobConfig) {
configService.persist(liteJobConfig);
return configService.load(false);
}
load()源码如下:
/**
* 读取作业配置.
*
* @param fromCache 是否从缓存中读取
* @return 作业配置
*/
public LiteJobConfiguration load(final boolean fromCache) {
String result;
if (fromCache) {
result = jobNodeStorage.getJobNodeData(ConfigurationNode.ROOT);
if (null == result) {
result = jobNodeStorage.getJobNodeDataDirectly(ConfigurationNode.ROOT);
}
} else {
result = jobNodeStorage.getJobNodeDataDirectly(ConfigurationNode.ROOT);
}
return LiteJobConfigurationGsonFactory.fromJson(result);
}
可以发现这块load有两种,一种是从缓存(这里的缓存使用Map来实现的TreeCache)中获取getJobNodeData,一种是从注册中心也就是zookeeper中获取getJobNodeDataDirectly。load的时候,根据的是zk的路径,其实也就是任务的jobName,所以我们要尽量避免任务名称的重复。
elastic-job动态添加定时任务的更多相关文章
- Quartz动态添加定时任务执行sql(服务启动添加+手动添加)
系统用来每天插入视图数据... 一.数据库表设计 1.接口配置表(t_m_db_interface_config) 2.接口日志表(t_m_db_interface_log) 3.前端配置页面 查询页 ...
- Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务
Celery 分布式任务队列快速入门 以及在Django中动态添加定时任务 转自 金角大王 http://www.cnblogs.com/alex3714/articles/6351797.html ...
- 动态添加定时任务-quartz定时器
Quartz动态添加.修改和删除定时任务 在项目中有一个需求,需要灵活配置调度任务时间,刚开始用的Java自带的java.util.Timer类,通过调度一个java.util.TimerTask任务 ...
- Celery动态添加定时任务
背景 业务需求:用户可创建多个多人任务,需要在任务截止时间前一天提醒所有参与者 技术选型: Celery:分布式任务队列.实现异步与定时 django-celery-beat:实现动态添加定时任务,即 ...
- Spring动态添加定时任务
Spring动态添加定时任务 一.背景 二.需求和实现思路 1.能够动态的添加一个定时任务. 2.能够取消定时任务的执行. 3.动态的修改任务执行的时间. 4.获取定时任务执行的异常 三.代码实现 四 ...
- Spring+Quartz实现动态添加定时任务
发布时间:2018-12-03 技术:spring4.0.2+quartz2.2.1 概述 在最近工作中,由于涉及到定时任务特别多,而这些工作又是由下属去完成的,在生成环境中经常会出现业务逻辑 ...
- elastic job 动态设置定时任务
1. 版本 <!-- import elastic-job lite core --> <dependency> <groupId>com.dangdang< ...
- Elastic-Job:动态添加任务,支持动态分片
多情只有春庭月,犹为离人照落花. 概述 因项目中使用到定时任务,且服务部署多实例,因此需要解决定时任务重复执行的问题.即在同一时间点,每一个定时任务只在一个节点上执行.常见的开源方案,如 elasti ...
- Quartz动态添加,修改,删除任务(暂停,任务状态,恢复,最近触发时间)
首页 博客 学院 下载 图文课 论坛 APP 问答 商城 VIP会员 活动 招聘 ITeye GitChat 写博客 小程序 消息 登录注册 关闭 quartz_Cron表达式一分钟教程 09-05 ...
随机推荐
- Zookeeper客户端cli_st为何在crontab中运行不正常?
实践中,发现直接在命令行终端运行cli_st时,能够得到预期的结果,但一将它放到crontab中,则只收到: bye 相关的一段clit_st源代码如下: if (FD_ISSET(, &rf ...
- 解决idea gradle构建Received fatal alert: handshake_failure问题
Gradle是一款强大的构建工具,但是搭建项目运行环境总是非常头痛,各种网络原因会导致项目不能成功的导入. 说一下这个问题的解决办法,折腾了很久终于解决了. javax.net.ssl.SSLHand ...
- PostgreSQL 表空间
PostgreSQL 表空间 一 介绍使用表空间可以将不同的表放到不同的存储介质或不同的文件系统下,实际上是为表指定一个存储的目录.创建数据库,表,索引时可以指定表空间,将数据库,表,索引放到指定的目 ...
- 为Visual Studio添加一个“编码的UI测试生成器”的快捷方式
在添加CodedUI测试用例时,经常需要查看捕获控件的属性.按照常规的方式,只有在添加一个全新的CodedUI编码测试时才能查看捕获控件的属性,这样很不方便. 下面介绍在Visual Studio工具 ...
- C# 使用 COALESCE 表达式简化 Null 检查
下面这个判断 null 的语句: a == null ? b: a 可以用 COALESCE 表达式,简化成: a ?? b
- WPF相关资料集锦
微软官方资料 .NET Framework源代码 https://referencesource.microsoft.com/ 微软官方文档 https://docs.microsoft.com/en ...
- python网络编程--线程的方法,线程池
一.线程的其他方法(Thread其他属性和方法) ident() 获取线程id Thread实例对象的方法 isAlive() 设置线程名 getName() 返回线程名 setName() 设置线程 ...
- python全栈开发_day31_OSI七层协议和c/s架构
一:OSI七层协议 应用层 =>表示层 =>会话层 =>传输层 =>网络层 =>数据链路层 =>物理连接层 二:c/s架构 b/s的本质也是c/s 手机端:好像cs ...
- “全栈2019”Java第九十三章:内部类应用场景(迭代器设计模式)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- vue 路由传参
mode:路由的形式 用的哪种路由 1.hash 路由 会带#号的哈希值 默认是hash路由 2.history路由 不会带#的 单页面开发首屏加载慢怎么解决?单页面开发首屏加载白屏怎 ...