创建时间: 2019/7/13 11:57
作者: sunpengwei1992@aliyun.com

elastic-job-lite简介

  • elastic-job是当当网开源的分布式任务调度系统,基于quartz二次开发实现的,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。
  • 前者主要定位为轻量级,去中心化的的分布式任务调度解决方案,是以jar包的形式提供,后者采用自研Mesos Framework的解决方案,额外提供资源治理、应用分发以及进程隔离等功能,
  • 我们今天主要说的是elastic-job-lite,cloud放在下一期讲解,目前最新版本是3.0.0.M1-SNAPSHOT,已经停止更新了
  • 但是使用的人,公司和教程还是很多的,遇到问题基本通过搜索可以解决的,解决不了的可以研究源码(还是相对比较好理解的)可以放心的使用。

    elastic-job-lite架构

  • elastic-job-lite轻量级的,去中心化的,上面说过他是基于quartz的,所以他的调度由使用其jar的项目驱动的,引入了zookeeper和分片的概念的为多台机器调度提供了协调和并行,并且配备一个运维端来管理job


  • elastic-job-lite架构图
    elastic-job-lite入门以及架构原理分析 - 图1

从上图我们可以看出,elastic-job-lite是以zookeeper作为注册中心的,console作为控制台和服务端解构,直接操纵zk改变job的配置信息,服务端启动时连接zk,注册job,初始化Scheuler,进行leader选举,分片,然后按照job配置信息调度作业,支持作业执行中的监控,event发送,失败转移等


  • elastic-job-lite部署图
    elastic-job-lite入门以及架构原理分析 - 图2

elastic-web控制台部署一台机器(也只能部署一台,有点坑),原因是elsatic-web通过界面添加zk的地址,写入本台机器文件中,这是有状态的,如果部署多台,负载均衡后,你再页面看到的信息多次访问后会不一致,因为会调用到不同的机器上,看下面的图,就理解了,如果想要多台做负载均衡,做HA,需要对这块做二次开发。(一般小公司一台足够了,web没什么压力)
elastic-job-lite入门以及架构原理分析 - 图3

elastic-job-lite使用

elastic-job-lite 入门使用

  • 首先准备好zk集群,elastic-job-lite使用zk作为注册中心
  • 在自己的项目中引入maven依赖

    1. <dependency>
    2. <groupId>com.dangdang</groupId>
    3. <artifactId>elastic-job-lite-core</artifactId>
    4. <version>3.0.0.M1-SNAPSHOT</version>
    5. </dependency>
  • elastic-job-lite支持两种作业类型,我们可以根据自己的业务需求选择合适作业类型

    • io.elasticjob.lite.api.simple.SimpleJob 实现此接口代表这个作业时简单累型作业
    • io.elasticjob.lite.api.dataflow.DataflowJob 实现此接口代表这个作业是支持流处理的作业
    • io.elasticjob.lite.api.script.ScriptJob 实现此接口代表这个作业是一个脚本作业

      1. //简单作业类型
      2. public class MyElasticJob implements SimpleJob {
      3. @Override
      4. public void execute(ShardingContext context) {
      5. }
      6. }

      简单作业类型我们实现SimpleJob接口中的execute方法,在里面处理自己的业务需求,调度器通过配置的cron表达式进行调度。

      1. //流处理作业类型
      2. public class MyElasticJob implements DataflowJob<T> {
      3. //抓取数据
      4. @Override
      5. public List<T> fetchData(ShardingContext shardingContext) {
      6. return null;
      7. }
      8. //执行数据
      9. @Override
      10. public void processData(ShardingContext shardingContext, List<T> list){
      11. {
      12. }

      流处理作业,需要实现DataflowJob中的两个方法(fetchData,processData),第一个方法负责抓取数据,抓取之后交给第二个方法执行。

      1. //脚本作业
      2. public class MyElasticJob implements ScriptJob {
      3. }

      elastic-job-lite三种作业的配置相关

  • elastic-job-lite作业配置的类图是这样的

elastic-job-lite入门以及架构原理分析 - 图4

  • 我们分析上面类图:
    • JobCoreConfiguration类定义了job作业核心配置属性
    • JobTypeConfiguration, Job类型的配置接口,有三个实现类,对应上面三种类型的作业,JobTypeConfiguration接口定义了获取JobCoreConfiguration类的方法
    • JobRootConfiguration, Job跟配置接口,定义了获取JobTypeConfiguration实现类的方法
    • LiteJobConfiguration类实现了JobRootConfiguration接口
  • 接下来我们分析这写类中定义的job配置属性
    | 属性 | 所属类 | 描述 | 简单 | 流处理 | 脚本 | | —- | —- | —- | —- | —- | —- | | jobName | JobCoreConfiguration | 名称 | 是 | 是 | 是 | | cron | JobCoreConfiguration | 时间表达式 | 是 | 是 | 是 | | shardingTotalCount | JobCoreConfiguration | 任务分片的总数 | 是 | 是 | 是 | | shardingItemParameters | JobCoreConfiguration | 每个分片对应的参数 | 是 | 是 | 是 | | jobParameter | JobCoreConfiguration | job从外部传入的参数 | 是 | 是 | 是 | | failover | JobCoreConfiguration | 是否开启失效转移 | 是 | 是 | 是 | | misfire | JobCoreConfiguration | 是否开启错过执行 | 是 | 是 | 是 | | description | JobCoreConfiguration | 任务描述 | 是 | 是 | 是 | | jobProperties | JobCoreConfiguration | 任务的一些属性配置 | 是 | 是 | 是 | | monitorExecution | LiteJobConfiguration | 是否开启监控 | 是 | 是 | 是 | | maxTimeDiffSeconds | LiteJobConfiguration | 本机和注册中心最大时间误差数 | 是 | 是 | 是 | | moinitorPort | LiteJobConfiguration | 监控u的那口 | 是 | 是 | 是 | | jobShardingStrategyClass | LiteJobConfiguration | 分片策略类 | 是 | 是 | 是 | | disabled | LiteJobConfiguration | 设置作业是否启动时禁止 | 是 | 是 | 是 | | overwrite | LiteJobConfiguration | 是否重写配置 | 是 | 是 | 是 | | streamingProcess | DataflowJobConfiguration | 是否开启流执行 | 否 | 是 | 否 | | scriptCommandLine | ScriptJobConfiguration | 脚本命令行 | 否 | 否 | 是 |

elastic-job-lite任务执行架构图

elastic-job-lite入门以及架构原理分析 - 图5

  • 在elastic-job-lite中,由调度器统一调度job,每种类型的job都对应一个调度器(目前调度器只有一种实现SpringJobScheduler),准备说是一个job对应一个scheduler,每种类型的job执行方法不一样,Simple类型通过执行execute方法,方法入参会携带分片参数决定当前机器处理那些分片的数据,DataFlow类型执行fetch方法,也是携带分片参数抓取属于当前机器处理的数据交给execute方法执行,Script类型是通过触发一个脚本来执行脚本中的业务逻辑,这个脚本可以是window下的.exe文件,也可以是python等文件

    elastic-job-lite的作业执行流程图

elastic-job-lite入门以及架构原理分析 - 图6

  • 上图详细描述elastic-job-lite中一个任务的执行流程,从quartz中一个job运行线程开始,调用LiteJob的execute方法,紧接着根据job的类型创建JobExecutor,开始执行jobExecutor,根据模板设计模式,父类AbstractExecutor规定了job的执行流程,子类重写了具体不同job类型执行时的同逻辑。
  • 描述一下各个方法的作用
    • checkJobExecutionEnvironment检查作业运行环境
    • getShardingContext获取作业的分片的上下文
    • postJobStatusTraceEvent发送作业状态跟踪时间
    • misfireRunning错过执行检查和设置
    • beforeJobExecuted作业执行前监听器执行
    • execute执行作业
    • isExecuteMisfired是否执行错过执行
    • failoverIfNecessary失效转移是否执行
    • afterJobExecuted作业执行后监听器执行

      elastic-job-lite启动流程

elastic-job-lite入门以及架构原理分析 - 图7
首先启动连接注册中心k,并且进行初始化,创建zk客户端,接着作业调度器JobScheduler,执行调度器的init方法,在init方法中做如下事情

  1. 往注册中心更新jobConfig
  2. 创建job调取器控制中心
  3. 注册job
  4. 注册job启动信息
    1. 开启关于job的zk监听器
    2. 主节点选举
    3. 持久化作业服务器上线信息
    4. 持久化作业运行实例信息
    5. 设置重新分片的标记
    6. 初始化作业监听服务
    7. 启动调解分布式作业不一致状态服务

      elastic-job-lite优缺点

      从上面的分析我想大家已经能得出一些elastic-job-lite的一些利弊信息了,这里我在归纳总结一下,
      优点
  1. 轻量级,简单,依赖少,只需一个zk就可以使用起来
  2. 支持多种作业类型,分片,失效转移,错过执行,动态新增,删除节点
  3. 简单的可视化管理
  4. 方便和spring整合,springboot整合

缺点

  1. 占用业务机器资源,资源调度和业务执行没有解耦
  2. zk作为注册中心不友好,不支持高可用
  3. 不支持复杂的作业管理(作业依赖),一些复杂业务场景不可使用
  4. 可视化相对简单,作业监控也比较简单
  5. 对单次执行不太友好

欢迎大家关注微信公众号:“golang那点事”,更多精彩期待你的到来
GoLang公众号.jpg