之前写过了关于定时任务的一篇文章,一般来说在实际生产中都是需要用分布式调度来完成的。因为单机的处理有限,也不符合高可用。而且在单机下定时任务没什么问题,但是如果部署了多台服务,同时如果每台服务都有定时任务,就必须合理的控制让同一时间只有一个定时任务执行,避免混乱和错误出现。由此可见,分布式的任务调度很重要 。
1.Elastic-Job 介绍Elastic-Job是一个分布式调度的解决方案,当当网的开源方案。由两个相互独立的子项目 ElasticJob-Lite 和 ElasticJob-Cloud 组成。
Elastic-Job 官网地址: Elastic-Job介绍 + 帮助文档
功能列表:
- 分布式调度协调
在分布式环境中,任务能够按照指定的调度策略执行,能够避免统一任务多实例重复执行。 - 丰富的调度策略
基于成熟的定时任务框架Quartz cron表达式执行定时任务。 - 弹性扩容缩容
当集群中增加一个实例,它应当能够被选举执行任务;当集群减少一个实例时,他所执行的任务能被转移到别的示例中执行。 - 失效转移
某实例在任务失败之后,会被转移到其他实例执行。 - 错过执行任务重触发
若因某种原因导致作业错过执行,自动记录错误执行的作业,并在下次作业完成后自动触发。 - 支持并行调度
支持任务分片,任务片是指将一个任务分成多个小任务在多个实例同时执行。 - 作业分片一致性
当任务被分片后,保证同一分片在分布式环境中仅有一个执行实例。 - 支持作业生命周期操作
可以动态对任务进行开启及停止操作。
- JDK要求1.8及其以上版本。
- Maven要求3.5.0及其以上版本。
- ZooKeeper要求3.6.0及其以上版本。
- Mesos要求11.0及其兼容版本。
添加如下依赖:
3. ZooKeeper 简单介绍com.dangdang elastic-job-lite-spring 2.1.5 elastic-job-lite-core com.dangdang 2.1.5
ZooKeeper是分布式协调的框架,配置维护、域名服务、分布式同步、组服务,有分布式独享锁、选举、队列的功能。
JavaGuide 中详细的介绍了ZooKeeper: JavaGuide
ZooKeeper 安装:安装教程
ZooKeeper 中的地址serverList和名称namespace需要配置一下,有两种方式可以参考:
1.在配置文件中去配置
regCenter.serverList=localhost:2181 regCenter.namespace=elasticjob
2.在文件中写死
创建一个JobRegistryCenterConfig,如果使用第二种方法就把下面里面包含serverList和namespace的值的地方都写死即可。
@Configuration
@ConditionalOnexpression("'${regCenter.serverList}'.length() > 0")
public class JobRegistryCenterConfig {
@Bean(initMethod = "init")
public ZookeeperRegistryCenter regCenter(@Value("${regCenter.serverList}") final String serverList,
@Value("${regCenter.namespace}") final String namespace) {
return new ZookeeperRegistryCenter(new ZookeeperConfiguration(serverList, namespace));
}
}
4. 定时任务配置
作业配置:
package cn.musite.elastic;
import cn.musite.elastic.job.MyElasticJob;
import com.dangdang.ddframe.job.config.JobCoreConfiguration;
import com.dangdang.ddframe.job.config.simple.SimpleJobConfiguration;
import com.dangdang.ddframe.job.lite.api.JobScheduler;
import com.dangdang.ddframe.job.lite.config.LiteJobConfiguration;
import com.dangdang.ddframe.job.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.job.reg.zookeeper.ZookeeperRegistryCenter;
public class JobDemo {
public static void main(String[] args) {
//创建JobScheduler,然后init初始化
// 参数1:注册中心zookeeper配置
// 参数2:任务相关配置
new JobScheduler(createRegistryCenter(), createJobConfiguration()).init();
}
private static CoordinatorRegistryCenter createRegistryCenter() {
//配置zookeeper 地址和名称
ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("localhost:2181", "elastic-job-demo");
//设置超时时间
zookeeperConfiguration.setSessionTimeoutMilliseconds(100);
//创造注册中心配置
CoordinatorRegistryCenter regCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
regCenter.init();
return regCenter;
}
private static LiteJobConfiguration createJobConfiguration() {
// 创建作业配置
// 定义作业核心配置
JobCoreConfiguration simpleCoreConfig = JobCoreConfiguration.newBuilder("demoSimpleJob","0/5 * * * * ?",1).build();
//定义SIMPLE类型配置
SimpleJobConfiguration simpleJobConfig = new SimpleJobConfiguration(simpleCoreConfig, MyElasticJob.class.getCanonicalName());
//定义Lite作业根配置
LiteJobConfiguration simpleJobRootConfig = LiteJobConfiguration.newBuilder(simpleJobConfig).build();
return simpleJobRootConfig;
}
}
启动类:
package cn.musite.elastic.job;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import java.util.Date;
public class MyElasticJob implements SimpleJob {
public void execute(ShardingContext shardingContext){
System.out.println("定时任务开始执行了==>"+ new Date());
}
}
5. 结果测试
- 运行单个程序,查看是否按照corn表达式的内容进行任务的调度。
- 运行多个程序(集群),查看是否只会有一个实例进行任务调度
- 运行多个程序后,把正在进行任务调度的进程关闭,查看其他进程是否能继续进行任务调度。



