分布式任务调度解决方案-Elastic-Job

任务调度目前存在的问题

基于Linux Crontab的定时任务执行器为例进行介绍。其存在如下问题:

  • 无法集中管理任务
  • 不能水平扩展
  • 无可视化界面操作
  • 存在单点故障

除了Linux Crontab,在Java这块的方案还有Quartz,但Quartz缺少分布式并行调度的功能。其问题很明显:

  • 当项目是一个单体应用时,基于Quartz开发一个定时任务,可以正常地运行。
  • 当项目做了负载,扩充到三个节点时,三个节点上的任务会同时执行,导致数据混乱。要保证同时执行的数据没问题,需要引入分布式锁来调度,难度增大。

在分布式架构环境中使用Quartz已经不能更好的满足我们需求,我们需要使用专业的分布式调度框架,这里介绍下Elastic-job。

Elastic-Job简介

Elastic-Job是当当网开源的一个分布式任务调度解决方案,基于Quartz二次开发的,由两个相互独立的子项 目Elastic-Job-Lite和Elastic-Job-Cloud组成。

Elastic-Job-Lite:为轻量级无中心化解决方案,使用JAR包提供分布式任务的调度和治理。

Elastic-Job-Cloud:使用Mesos+Docker的解决方案,额外提供资源治理、应用分发及进程隔离等服务。

官网地址:http://elasticjob.io/

github地址:https://github.com/elasticjob

主要功能介绍

  • 在分布式环境中,任务能够按指定的调度策略执行,并且能够避免同一任务多实例重复执行
  • 丰富的调度策略基于成熟的定时任务作业框架Quartz cron表达式执行定时任务
  • 弹性扩容缩容当集群中增加某一个实例,它应当也能够被选举并执行任务;当集群减少一个实例时,它所执行的任务能被转移到别的实例来执行。
  • 失效转移某实例在任务执行失败后,会被转移到其他实例执行
  • 错过执行作业重触发若因某种原因导致作业错过执行,自动记录错过执行的作业,并在上次作业 完成后自动触发。
  • 支持并行调度支持任务分片,任务分片是指将一个任务分为多个小任务项在多个实例同时执行。
  • 作业分片一致性当任务被分片后,保证同一分片在分布式环境中仅一个执行实例。

Elastic-Job-Lite所需依赖

Elastic-Job依赖于Zookeeper进行分布式协调,所以需要安装Zookeeper软件。

zookeeper是一个开源的分布式协调服务,提供分布式数据一致性解决方案,分布式应用程序可以实现数据发布订阅、负载均衡、命名服务、集群管理分布式锁、分布式队列等功能。不做详细赘述。

ZooKeeper的安装

Zookeeper是安装Kafka集群的必要组件,Kafka通过Zookeeper来实施对元数据信息的管理,包括集

群、主题、分区等内容。

ZooKeeper官网:http://zookeeper.apache.org/

修改Zookeeper的配置文件,首先进入安装路径conf目录,并将zoo_sample.cfg文件修改为 zoo.cfg,并对核心参数进行配置。

Zookeeper配置文件详解

# The number of milliseconds of each tick # zk服务器的心跳时间
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
# 投票选举新Leader的初始化时间
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# do not use /tmp for storage, /tmp here is just # example sakes.
# 数据目录
dataDir=temp/zookeeper/data
# 日志目录
dataLogDir=temp/zookeeper/log
# the port at which the clients will connect
# Zookeeper对外服务端口,保持默认
clientPort=2181

启动zookeeper

[root@localhost bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.14/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

其他操作

停止 ./zkServer.sh stop
查看状态 ./zkServer.sh status

ZooKeeper树形节点图

分布式任务调度解决方案-Elastic-Job_第1张图片

Elastic-Job-Lite应用

  • 引入依赖jar包

<!-- https://mvnrepository.com/artifact/com.dangdang/elastic-job-lite-core -->
<dependency>
<groupId>com.dangdang</groupId> <artifactId>elastic-job-lite-core</artifactId> <version>2.1.5</version>
</dependency>
  • 定时任务实例代码(不分片)

public class ElasticjobMainNoShard {
    public static void main(String[] args) {
        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("172.16.115.129:2181","data-archive-job-add");
        CoordinatorRegistryCenter coordinatorRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        coordinatorRegistryCenter.init();

        // 配置任务(时间事件、定时任务业务逻辑、调度器)
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("archive-job-add", "*/1 * * * * ?", 1).build();
        SimpleJobConfiguration simpleJobConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, ArchivieJobInsert.class.getName());
        JobScheduler jobScheduler = new JobScheduler(coordinatorRegistryCenter, LiteJobConfiguration.newBuilder(simpleJobConfiguration).overwrite(true).build());
        jobScheduler.init();

    }
}

在分布式环境中,任务能够按指定的调度策略执行,并且能够避免同一任务多实例重复执行,当开启一个服务执行任务时,会将leader设置为开启的服务,当开启两个任务时,leader由于被服务二抢走,服务一会停止继续执行。保证只有一个会去执行。

服务一开启:
分布式任务调度解决方案-Elastic-Job_第2张图片

服务二开启:
分布式任务调度解决方案-Elastic-Job_第3张图片

服务一:
分布式任务调度解决方案-Elastic-Job_第4张图片
服务二:
分布式任务调度解决方案-Elastic-Job_第5张图片

定时任务(分片)

一个大的非常耗时的作业Job,比如:一次要处理一亿的数据,那这一亿的数据存储在数据库中,如果用一个作业节点处理一亿数据要很久,在互联网领域是不太能接受的,互联网领域更希望机器的增加去横向扩展处理能力。所以,ElasticJob可以把作业分为多个的task(每一个task就是一个任务分片),每 一个task交给具体的一个机器实例去处理(一个机器实例是可以处理多个task的),但是具体每个task 执行什么逻辑由我们自己来指定。
分布式任务调度解决方案-Elastic-Job_第6张图片

Strategy策略定义这些分片项怎么去分配到各个机器上去,默认是平均去分,可以定制,比如某一个机 器负载 比较高或者预配置比较高,那么就可以写策略。分片和作业本身是通过一个注册中心协调的,因为在分布式环境下,状态数据肯定集中到一点,才可以在分布式中沟通。

分片代码实例(以下代码将任务分配了三个分片)

public class ElasticjobMainShard {
    public static void main(String[] args) {

        ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration("172.16.115.129:2181","data-archive-job");
        CoordinatorRegistryCenter coordinatorRegistryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
        coordinatorRegistryCenter.init();

        // 配置任务(时间事件、定时任务业务逻辑、调度器)
        JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration
                .newBuilder("archive-job", "*/2 * * * * ?", 3)
                .shardingItemParameters("0=bachelor,1=master,2=doctor").build();
        SimpleJobConfiguration simpleJobConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, ArchivieJobShard.class.getName());

        JobScheduler jobScheduler = new JobScheduler(coordinatorRegistryCenter, LiteJobConfiguration.newBuilder(simpleJobConfiguration).overwrite(true).build());
        jobScheduler.init();

    }
}

多个服务处理效果

支持并行调度支持任务分片,任务分片是指将一个任务分为多个小任务项在多个实例同时执行。

当开启三个服务时,每个服务各自会处理一个分片。

分片
分布式任务调度解决方案-Elastic-Job_第7张图片

分片1
分布式任务调度解决方案-Elastic-Job_第8张图片

分片
分布式任务调度解决方案-Elastic-Job_第9张图片

服务挂掉处理效果

当某一个或某几个服务挂掉后,会由活着的服务自动帮助处理任务。

关闭个后,其中一个服务会处理连个任务,另一个服务会处理一个任务。
分布式任务调度解决方案-Elastic-Job_第10张图片

当关闭两个后,所有任务都由剩下唯一的一个服务进行处理。
分布式任务调度解决方案-Elastic-Job_第11张图片

Zookeeper不分片与分片节点异同

通过zookepper的节点可以看出差异。任务分片时通过添加zookeeper的顺序节点实现。
分布式任务调度解决方案-Elastic-Job_第12张图片

你可能感兴趣的:(其他,zookeeper,分布式)