开发指南

代码开发

作业类型

目前提供3种作业类型,分别是Simple,DataFlow和Script。

DataFlow类型用于处理数据流,它又提供2种作业类型,分别是ThroughputDataFlow和SequenceDataFlow。需要继承相应的抽象类。

Script类型用于处理脚本,可直接使用,无需编码。

方法参数shardingContext包含作业配置,分片和运行时信息。可通过getShardingTotalCount(),getShardingItems()等方法分别获取分片总数,运行在本作业服务器的分片序列号集合等。

Simple类型作业

Simple类型作业意为简单实现,未经任何封装的类型。需要继承AbstractSimpleElasticJob,该类只提供了一个方法用于覆盖,此方法将被定时执行。用于执行普通的定时任务,与Quartz原生接口相似,只是增加了弹性扩缩容和分片等功能。

public class JobMain {  

    public static void main(final String[] args) {
long startTimeoutMills = 5000L;
long completeTimeoutMills = 10000L;
new JobScheduler(regCenter, jobConfig, new MyDistributeOnceElasticJobListener(startTimeoutMills, completeTimeoutMills)).init();
}
}

ThroughputDataFlow类型作业

ThroughputDataFlow类型作业意为高吞吐的数据流作业。需要继承AbstractInpidualThroughputDataFlowElasticJob并可以指定返回值泛型,该类提供3个方法可覆盖,分别用于抓取数据,处理数据和指定是否流式处理数据。可以获取数据处理成功失败次数等辅助监控信息。如果流式处理数据,fetchData方法的返回值只有为null或长度为空时,作业才会停止执行,否则作业会一直运行下去;非流式处理数据则只会在每次作业执行过程中执行一次fetchData方法和processData方法,即完成本次作业。流式数据处理参照TbSchedule设计,适用于不间歇的数据处理。

作业执行时会将fetchData的数据传递给processData处理,其中processData得到的数据是通过多线程(线程池大小可配)拆分的。如果采用流式作业处理方式,建议processData处理数据后更新其状态,避免fetchData再次抓取到,从而使得作业永远不会停止。processData的返回值用于表示数据是否处理成功,抛出异常或者返回false将会在统计信息中归入失败次数,返回true则归入成功次数。

public class MyElasticJob extends AbstractInpidualThroughputDataFlowElasticJob {  

    @Override
public List fetchData(JobExecutionMultipleShardingContext context) {
Map<integer, string=""> offset = context.getOffsets();
List result = // get data from database by sharding items and by offset
return result;
} @Override
public boolean processData(JobExecutionMultipleShardingContext context, Foo data) {
// process data
// ... // store offset
for (int each : context.getShardingItems()) {
updateOffset(each, "your offset, maybe id");
}
return true;
}
}

SequenceDataFlow类型作业

SequenceDataFlow类型作业和ThroughputDataFlow作业类型极为相似,所不同的是ThroughputDataFlow作业类型可以将获取到的数据多线程处理,但不会保证多线程处理数据的顺序。如:从2个分片共获取到100条数据,第1个分片40条,第2个分片60条,配置为两个线程处理,则第1个线程处理前50条数据,第2个线程处理后50条数据,无视分片项;SequenceDataFlow类型作业则根据当前服务器所分配的分片项数量进行多线程处理,每个分片项使用同一线程处理,防止了同一分片的数据被多线程处理,从而导致的顺序问题。如:从2个分片共获取到100条数据,第1个分片40条,第2个分片60条,则系统自动分配两个线程处理,第1个线程处理第1个分片的40条数据,第2个线程处理第2个分片的60条数据。由于ThroughputDataFlow作业可以使用多于分片项的任意线程数处理,所以性能调优的可能会优于SequenceDataFlow作业。

public class MyElasticJob extends AbstractInpidualSequenceDataFlowElasticJob {  

    @Override
public List fetchData(JobExecutionSingleShardingContext context) {
int offset = context.getOffset();
List result = // get data from database by sharding items and by offset
return result;
} @Override
public boolean processData(JobExecutionSingleShardingContext context, Foo data) {
// process data
// ... // store offset
updateOffset(context.getShardingItem(), "your offset, maybe id");
return true;
}
}

Script类型作业

Script类型作业意为脚本类型作业,支持shell,Python,perl等所有类型脚本。只需通过控制台/代码配置scriptCommandLine即可。执行脚本路径可以包含参数,最后一个参数为作业运行时信息.

#!/bin/bash
echo sharding execution context is $*

作业运行时输出

sharding execution context is {"shardingItems":[0,1,2,3,4,5,6,7,8,9],"shardingItemParameters":{},"offsets":{},"jobName":"scriptElasticDemoJob","shardingTotalCount":10,"jobParameter":"","monitorExecution":true,"fetchDataCount":1}

批量处理

为了提高数据处理效率,数据流类型作业提供了批量处理数据的功能。之前逐条处理数据的两个抽象类分别是AbstractInpidualThroughputDataFlowElasticJob和AbstractInpidualSequenceDataFlowElasticJob,批量处理则使用另外两个接口AbstractBatchThroughputDataFlowElasticJob和AbstractBatchSequenceDataFlowElasticJob。不同之处在于processData方法的返回值从boolean类型变为int类型,用于表示一批数据处理的成功数量,第二个入参则转变为List数据集合。

异常处理

elastic-job在最上层接口提供了handleJobExecutionException方法,使用作业时可以覆盖此方法,并使用quartz提供的JobExecutionException控制异常后作业的声明周期。默认实现是直接将异常抛出。示例:

任务监听配置

可以通过配置多个任务监听器,在任务执行前和执行后执行监听的方法。监听器分为每台作业节点均执行和分布式场景中仅单一节点执行两种。

每台作业节点均执行的监听

若作业处理作业服务器的文件,处理完成后删除文件,可考虑使用每个节点均执行清理任务。此类型任务实现简单,且无需考虑全局分布式任务是否完成,请尽量使用此类型监听器。

步骤:

定义监听器

import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.api.listener.ElasticJobListener; public class MyElasticJobListener implements ElasticJobListener { @Override
public void beforeJobExecuted(final JobExecutionMultipleShardingContext shardingContext) {
// do something ...
} @Override
public void afterJobExecuted(final JobExecutionMultipleShardingContext shardingContext) {
// do something ...
}
}

将监听器作为参数传入JobScheduler

public class JobMain {  

    public static void main(final String[] args) {
new JobScheduler(regCenter, jobConfig, new MyElasticJobListener()).init();
}
}

分布式场景中仅单一节点执行的监听

若作业处理数据库数据,处理完成后只需一个节点完成数据清理任务即可。此类型任务处理复杂,需同步分布式环境下作业的状态同步,提供了超时设置来避免作业不同步导致的死锁,请谨慎使用。

步骤:

定义监听器

import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.api.listener.AbstractDistributeOnceElasticJobListener; public final class TestDistributeOnceElasticJobListener extends AbstractDistributeOnceElasticJobListener { public TestDistributeOnceElasticJobListener(final long startTimeoutMills, final long completeTimeoutMills) {
super(startTimeoutMills, completeTimeoutMills);
} @Override
public void doBeforeJobExecutedAtLastStarted(final JobExecutionMultipleShardingContext shardingContext) {
// do something ...
} @Override
public void doAfterJobExecutedAtLastCompleted(final JobExecutionMultipleShardingContext shardingContext) {
// do something ...
}
}

将监听器作为参数传入JobScheduler

public class JobMain {  

    public static void main(final String[] args) {
long startTimeoutMills = 5000L;
long completeTimeoutMills = 10000L;
new JobScheduler(regCenter, jobConfig, new MyDistributeOnceElasticJobListener(startTimeoutMills, completeTimeoutMills)).init();
}
}

作业配置

spring容器配合使用作业,可以将作业Bean配置为Spring Bean,可在作业中通过依赖注入使用Spring容器管理的数据源等对象。可用placeholder占位符从属性文件中取值。

Spring命名空间配置

job:simple命名空间属性详细说明

属性名 类型 是否必填 缺省值 描述
id String   作业名称
class String   作业实现类,需实现ElasticJob接口,脚本型作业不需要配置
registry-center-ref String   注册中心Bean的引用,需引用reg:zookeeper的声明
cron String   cron表达式,用于配置作业触发时间
sharding-total-count int   作业分片总数
sharding-item-parameters String   分片序列号和参数用等号分隔,多个键值对用逗号分隔
分片序列号从0开始,不可大于或等于作业分片总数
如:
0=a,1=b,2=c
job-parameter String   作业自定义参数
可以配置多个相同的作业,但是用不同的参数作为不同的调度实例
monitor-execution boolean true 监控作业运行时状态
每次作业执行时间和间隔时间均非常短的情况,建议不监控作业运行时状态以提升效率。因为是瞬时状态,所以无必要监控。请用户自行增加数据堆积监控。并且不能保证数据重复选取,应在作业中实现幂等性。
每次作业执行时间和间隔时间均较长的情况,建议监控作业运行时状态,可保证数据不会重复选取。
monitor-port int -1 作业监控端口
建议配置作业监控端口, 方便开发者dump作业信息。
使用方法: echo “dump” | nc 127.0.0.1 9888
max-time-diff-seconds int -1 最大允许的本机与注册中心的时间误差秒数
如果时间误差超过配置秒数则作业启动时将抛异常
配置为-1表示不校验时间误差
failover boolean false 是否开启失效转移
仅monitorExecution开启,失效转移才有效
misfire boolean true 是否开启错过任务重新执行
job-sharding-strategy-class String true 作业分片策略实现类全路径
默认使用平均分配策略
详情参见:作业分片策略
description String   作业描述信息
disabled boolean false 作业是否禁止启动
可用于部署作业时,先禁止启动,部署结束后统一启动
overwrite boolean false 本地配置是否可覆盖注册中心配置
如果可覆盖,每次启动作业都以本地配置为准

job:dataflow命名空间属性详细说明

job:dataflow命名空间拥有job:simple命名空间的全部属性,以下仅列出特有属性

属性名 类型 是否必填 缺省值 描述
process-count-interval-seconds int 300 统计作业处理数据数量的间隔时间
单位:秒
concurrent-data-process-thread-count int CPU核数*2 同时处理数据的并发线程数
不能小于1
仅ThroughputDataFlow作业有效
fetch-data-count int 1 每次抓取的数据量
streaming-process boolean false 是否流式处理数据
如果流式处理数据, 则fetchData不返回空结果将持续执行作业
如果非流式处理数据, 则处理数据完成后作业结束

job:script命名空间属性详细说明,基本属性参照job:simple命名空间属性详细说明

job:script命名空间拥有job:simple命名空间的全部属性,以下仅列出特有属性

属性名 类型 是否必填 缺省值 描述
script-command-line String   脚本型作业执行命令行

job:listener命名空间属性详细说明

job:listener必须配置为job:bean的子元素

属性名 类型 是否必填 缺省值 描述
class String   前置后置任务监听实现类,需实现ElasticJobListener接口
started-timeout-milliseconds long Long.MAX_VALUE AbstractDistributeOnceElasticJobListener型监听器,最后一个作业执行前的执行方法的超时时间
单位:毫秒
completed-timeout-milliseconds long Long.MAX_VALUE AbstractDistributeOnceElasticJobListener型监听器,最后一个作业执行后的执行方法的超时时间
单位:毫秒

reg:bean命名空间属性详细说明

属性名 类型 是否必填 缺省值 描述
id String   注册中心在Spring容器中的主键
server-lists String   连接Zookeeper服务器的列表
包括IP地址和端口号
多个地址用逗号分隔
如: host1:2181,host2:2181
namespace String   Zookeeper的命名空间
base-sleep-time-milliseconds int 1000 等待重试的间隔时间的初始值
单位:毫秒
max-sleep-time-milliseconds int 3000 等待重试的间隔时间的最大值
单位:毫秒
max-retries int 3 最大重试次数
session-timeout-milliseconds int 60000 会话超时时间
单位:毫秒
connection-timeout-milliseconds int 15000 连接超时时间
单位:毫秒
digest String 无验证 连接Zookeeper的权限令牌
缺省为不需要权限验证

不使用Spring配置

如果不使用Spring框架,可以用如下方式启动作业。

import com.dangdang.ddframe.job.api.config.JobConfiguration;
import com.dangdang.ddframe.job.api.JobScheduler;
import com.dangdang.ddframe.reg.base.CoordinatorRegistryCenter;
import com.dangdang.ddframe.reg.zookeeper.ZookeeperConfiguration;
import com.dangdang.ddframe.reg.zookeeper.ZookeeperRegistryCenter;
import com.dangdang.example.elasticjob.core.job.SimpleJobDemo;
import com.dangdang.example.elasticjob.core.job.ThroughputDataFlowJobDemo;
import com.dangdang.example.elasticjob.core.job.SequenceDataFlowJobDemo;
import com.dangdang.ddframe.job.plugin.job.type.integrated.ScriptElasticJob; public class JobDemo { // 定义Zookeeper注册中心配置对象
private ZookeeperConfiguration zkConfig = new ZookeeperConfiguration("localhost:2181", "elastic-job-example", 1000, 3000, 3); // 定义Zookeeper注册中心
private CoordinatorRegistryCenter regCenter = new ZookeeperRegistryCenter(zkConfig); // 定义简单作业配置对象
private final SimpleJobConfiguration simpleJobConfig = JobConfigurationFactory.createSimpleJobConfigurationBuilder("simpleElasticDemoJob",
SimpleJobDemo.class, 10, "0/30 * * * * ?").build(); // 定义高吞吐流式处理的数据流作业配置对象
private final DataFlowJobConfiguration throughputJobConfig = JobConfigurationFactory.createDataFlowJobConfigurationBuilder("throughputDataFlowElasticDemoJob",
ThroughputDataFlowJobDemo.class, 10, "0/5 * * * * ?").streamingProcess(true).build(); // 定义顺序的数据流作业配置对象
private final DataFlowJobConfiguration sequenceJobConfig = JobConfigurationFactory.createDataFlowJobConfigurationBuilder("sequenceDataFlowElasticDemoJob",
SequenceDataFlowJobDemo.class, 10, "0/5 * * * * ?").build(); // 定义脚本作业配置对象
private final ScriptJobConfiguration scriptJobConfig = JobConfigurationFactory.createScriptJobConfigurationBuilder("scriptElasticDemoJob",
10, "0/5 * * * * ?", "test.sh").build(); public static void main(final String[] args) {
new JobDemo().init();
} private void init() {
// 连接注册中心
regCenter.init();
// 启动简单作业
new JobScheduler(regCenter, simpleJobConfig).init();
// 启动高吞吐流式处理的数据流作业
new JobScheduler(regCenter, throughputJobConfig).init();
// 启动顺序的数据流作业
new JobScheduler(regCenter, sequenceJobConfig).init();
// 启动脚本作业
new JobScheduler(regCenter, scriptJobConfig).init();
}
}

转载:https://www.2cto.com/kf/201611/566016.html

Elastic-Job开发指南的更多相关文章

  1. ASP.NET Aries 开源开发框架:开发指南(一)

    前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...

  2. FreeMarker模板开发指南知识点梳理

    freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...

  3. Jetty使用教程(四:21-22)—Jetty开发指南

    二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...

  4. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

  5. iOS原生地图开发指南续——大头针与自定义标注

    iOS原生地图开发指南续——大头针与自定义标注 出自:http://www.sxt.cn/info-6042-u-7372.html 在上一篇博客中http://my.oschina.net/u/23 ...

  6. Angularjs中文版本开发指南发布

    从本人开始在写关于Angularjs的文章开始,也算是见证了Angularjs在国内慢慢的火起来,如今的Angularjs正式如日中天.想知道为什么Angularjs会这么火,请移步angularjs ...

  7. nodejs开发指南读后感

    nodejs开发指南读后感 阅读目录 使用nodejs创建http服务器; supervisor的使用及nodejs常见的调式代码命令了解; 了解Node核心模块; ejs模板引擎 Express 理 ...

  8. Libgdx 开发指南——目录

    本系列文档选译自libgdx github项目 wiki : https://github.com/libgdx/libgdx/wiki 由于关于Libgdx的中文文档非常稀缺,因此在这里对官方Wik ...

  9. jQuery MiniUI 开发指南+API组件参考手册

    jQuery MiniUI 开发指南 本文档将逐步的讲解jQuery MiniUI的方方面面,从此您将踏上jQuery MiniUI的深入探索之旅.                 1.Hello M ...

  10. 《CSS3专业网页开发指南》笔记

    书本:<CSS3专业网页开发指南>(the book of css3) Peter Gasston 著    李景媛 吴晓嘉 译 第1章: 1.box-sizing : IE8及以上版本 ...

随机推荐

  1. 数据分析与展示---Pandas库入门

    简介 一:Pandas库的介绍 二:Pandas库的Series类型 (一)索引 (1)自动索引 (2)自定义索引 (二)Series类型创建 (1)列表创建 (2)标量值创建 (3)字典类型创建(将 ...

  2. bzoj千题计划146:bzoj3295: [Cqoi2011]动态逆序对

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 正着删除看做倒着添加 对答案有贡献的数对满足以下3个条件: 出现时间:i<=j 权值大小 ...

  3. SQL on Hadoop中用到的主要技术——MPP vs Runtime Framework

    转载声明 本文转载自盘点SQL on Hadoop中用到的主要技术,个人觉得该文章对于诸如Impala这样的MPP架构的SQL引擎和Runtime Framework架构的Hive/Spark SQL ...

  4. python 操作excel格式化及outlook正文,发送邮件

    import requests import time import os import arrow import pandas as pd import pandas.io.formats.exce ...

  5. 六、强大的 Stream API

    一.了解 Stream Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*).Stream 是 Java8 中处 ...

  6. python sqlite3 入门 (视频讲座)

    python sqlite3 入门 (视频讲座) an SQLite mini-series! - Simple Databases with Python 播放列表: YouTube https:/ ...

  7. Python排序算法之直接插入排序

    插入排序的主要思想是每次取一个列表元素与列表中已经排序好的列表段进行比较,然后插入从而得到新的排序好的列表段,最终获得排序好的列表. 比如,待排序列表为[49,38,65,97,76,13,27,49 ...

  8. [转载]Node入门 » 一本全面的Node.js教程

    http://www.nodebeginner.org/index-zh-cn.html 作者: Manuel Kiessling 翻译: goddyzhao & GrayZhang & ...

  9. soj1001. Alphacode

    1001. Alphacode Constraints Time Limit: 1 secs, Memory Limit: 32 MB Description Alice and Bob need t ...

  10. 微服务深入浅出(8)-- 配置中心Spring Cloud Config

    Config Server从本地读取配置文件 将所有的配置文件统一写带Config Server过程的目录下,Config Server暴露Http API接口,Config Client调用Conf ...