一 springboot整合

介绍就不多说了,只有这个框架是当当网开源的,支持分布式调度,分布式系统中非常合适(两个服务同时跑不会重复,并且可灵活配置分开分批处理数据,贼方便)!

这里主要还是用到zookeeper,如果没有zk环境,可以百度或者参考我之前的博客搭建

添加依赖,这里有一点,如果是在springcloud中的话,需要排除自带的curator依赖,因为cloud已经集成一些,会冲突:

  <!-- elastic-job -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>2.1.5</version>
<exclusions>
<exclusion>
<artifactId>curator-client</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
<exclusion>
<artifactId>curator-framework</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
<exclusion>
<artifactId>curator-recipes</artifactId>
<groupId>org.apache.curator</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.10.0</version>
</dependency>
</dependencies>

然后就是配置zk注册中心,分布式功能主要依赖这个,所有属性都从yml中注入,这里注意一点,可以把超时时间设置大一点:

@Configuration
public class ElasticRegCenterConfig {
/**
* 配置zookeeper注册中心
*/
@Bean(initMethod = "init") // 需要配置init执行初始化逻辑
public ZookeeperRegistryCenter regCenter(
@Value("${regCenter.serverList}") final String serverList,
@Value("${regCenter.namespace}") final String namespace) {
ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(serverList, namespace);
zookeeperConfiguration.setMaxRetries(3); //设置重试次数,可设置其他属性
zookeeperConfiguration.setSessionTimeoutMilliseconds(500000); //设置会话超时时间,尽量大一点,否则项目无法正常启动
return new ZookeeperRegistryCenter(zookeeperConfiguration);
}
}

然后就是配置job了,其实和spring的quartz配置都差不多,一个job类,一个调度类

这里先贴我的yml配置,任务执行周期,分片个数都从这里注入即可,分片使用后面单独说明:

二 simplejob

job类:

@Component
public class MySimpleJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
System.out.println(shardingContext.getJobName()+"执行:"+
"分片参数:"+shardingContext.getShardingParameter()+
",当前分片项:"+shardingContext.getShardingItem()+
",time:"+ LocalDate.now());
}
}

 

配置类,这里用到了一个工具方法,工具类放下面:

/**
* 配置MySimpleJob
*/
@Configuration
public class MySimpleJobConf {
@Autowired ZookeeperRegistryCenter regCenter;
@Autowired MySimpleJob mySimpleJob;
/**
* 配置任务调度: 参数: 任务
* zk注册中心
* 任务详情
*/
@Bean(initMethod = "init")
public JobScheduler simpleJobScheduler(@Value("${mySimpleJob.cron}") final String cron, //yml注入
@Value("${mySimpleJob.shardingTotalCount}") final int shardingTotalCount,
@Value("${mySimpleJob.shardingItemParameters}") final String shardingItemParameters) {
return new SpringJobScheduler(mySimpleJob, regCenter,
ElasticJobUtils.getSimpleJobConfiguration(
mySimpleJob.getClass(),
cron,
shardingTotalCount,
shardingItemParameters)
//,new MyElasticJobListener() 可配置监听器
);
}
}

工具类:

public class ElasticJobUtils {

    /**
* 创建简单任务详细信息
*/
public static LiteJobConfiguration getSimpleJobConfiguration(final Class<? extends SimpleJob> jobClass, //任务类
final String cron, // 运行周期配置
final int shardingTotalCount, //分片个数
final String shardingItemParameters) { // 分片参数
return LiteJobConfiguration.newBuilder(new SimpleJobConfiguration(
JobCoreConfiguration.newBuilder(jobClass.getName(), cron, shardingTotalCount)
.shardingItemParameters(shardingItemParameters).build()
, jobClass.getCanonicalName())
).overwrite(true).build();
} /**
* 创建流式作业配置
*/
public static LiteJobConfiguration getDataFlowJobConfiguration(final Class<? extends DataflowJob> jobClass, //任务类
final String cron, // 运行周期配置
final int shardingTotalCount, //分片个数
final String shardingItemParameters,
final Boolean streamingProcess //是否是流式作业
) { // 分片参数
return LiteJobConfiguration.newBuilder(new DataflowJobConfiguration(
JobCoreConfiguration.newBuilder(jobClass.getName(), cron, shardingTotalCount)
.shardingItemParameters(shardingItemParameters).build()
// true为流式作业,除非fetchData返回数据为null或者size为0,否则会一直执行
// false 非流式,只会按配置时间执行一次
, jobClass.getCanonicalName(),streamingProcess)
).overwrite(true).build();
}
}

测试:

三 dataflowjob

job类:

@Component
public class MyDataFlowJob implements DataflowJob<String> {
@Override
public List<String> fetchData(ShardingContext shardingContext) { //抓取数据
System.out.println("---------获取数据---------");
return Arrays.asList("1","2","3");
}
@Override
public void processData(ShardingContext shardingContext, List<String> list) {//处理数据
System.out.println("---------处理数据---------");
list.forEach(x-> System.out.println("数据处理:"+x));
}
}

配置类:

@Configuration
public class MyDataFlowJobConf {
@Autowired ZookeeperRegistryCenter regCenter;
@Autowired MyDataFlowJob myDataFlowJob;
/**
* 配置任务调度: 参数: 任务
* zk注册中心
* 任务详情
*/
@Bean(initMethod = "init")
public JobScheduler dataFlowJobScheduler(@Value("${myDataFlowJob.cron}") final String cron, //yml注入
@Value("${myDataFlowJob.shardingTotalCount}") final int shardingTotalCount,
@Value("${myDataFlowJob.shardingItemParameters}") final String shardingItemParameters) {
return new SpringJobScheduler(myDataFlowJob, regCenter,
ElasticJobUtils.getDataFlowJobConfiguration(
myDataFlowJob.getClass(),
cron,
shardingTotalCount,
shardingItemParameters,true)
//,new MyElasticJobListener() 可配置监听器
);
}
}

测试:

需要注意一点流式作业如果数据不为空会一直跑

四 scriptjob

脚本任务有一点,不需要创建类实例,否则会报错,参数直接传null即可

配置类:

@Configuration
public class MyScriptJobConf {
@Autowired ZookeeperRegistryCenter regCenter;
/**
* 配置任务调度: 参数: 任务
* zk注册中心
* 任务详情
*/
@Bean(initMethod = "init")
public JobScheduler scriptJobScheduler(@Value("${myScriptJob.cron}") final String cron, //yml注入
@Value("${myScriptJob.shardingTotalCount}") final int shardingTotalCount,
@Value("${myScriptJob.shardingItemParameters}") final String shardingItemParameters) {
return new SpringJobScheduler(null, regCenter,
ElasticJobUtils.getScriptJobConfiguration(
"script_job",
cron,
shardingTotalCount,
//命令或者脚本路径
shardingItemParameters,"echo hello")
//,new MyElasticJobListener() 可配置监听器
);
}
}

工具添加静态方法:

/**
* 创建脚本作业配置
*/
public static LiteJobConfiguration getScriptJobConfiguration(final String jobName, //任务名字
final String cron, // 运行周期配置
final int shardingTotalCount, //分片个数
final String shardingItemParameters,
final String scriptCommandLine //是脚本路径或者命令
) { // 分片参数
return LiteJobConfiguration.newBuilder(new ScriptJobConfiguration(
JobCoreConfiguration.newBuilder(jobName, cron, shardingTotalCount)
.shardingItemParameters(shardingItemParameters).build()
// 此处配置文件路径或者执行命令
, scriptCommandLine)
).overwrite(true).build();
}

测试:

五 分片用法

分片的目的就是通过配置分片个数,让不同的分片参数到不同的服务中去,比如配置了分片个数是2,那么分片一会到服务一中,分片二到服务二中

项目中根据分片参数来决定哪个服务处理哪些数据,比如  0=客户甲,1=客户乙,但是分片item是从1开始

分片算法默认是平均,可自定义,然后参数就是上面yml那种配置,比如2,就是 0=,1=  4就是0=,1=,2=,3=,两个服务的话服务一就是0,1的参数,服务二就是2,3的参数,并且分片item是3,4

然后要注意一点的是,这个分片识别是根据ip的,也就是说同一台电脑,跑两个程序没用,两个程序都会全部执行,还是会重复

主要是这个分片保证分布式中处理数据不重复,分片也会转移,即一个服务挂了之后,分片参数和item会自动转移到剩下服务中

六 事件追踪(即任务信息持久化到mysql)

需要提前创建btach_log数据库

配置数据源Bean,在任务配置中添加event

@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class JobDataSourceConf {
private String url;
private String username;
private String password;
private String driver_class_name; @Bean
@Primary
public DataSource hikariDataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driver_class_name);
return dataSource;
}

程序会自动创建两张表并添加记录

七 容易踩的坑

一 配置类中配置bean的时候,方法名不要重复,否则会发现任务不跑,

二 测试分布式的时候,必须跑在ip不一样的服务上,否则不会实现分片

三 我的版本再pom里面,springboot版本是2.0.6,版本不一样可能用法也有些区别

四 理论上xml更简单,但是我个人比较喜欢代码风格,哈哈

五 脚本任务不能新建实例,参数传null,且确认命令是否有权限

springboot整合elasticJob实战(纯代码开发三种任务类型用法)以及分片系统,事件追踪详解的更多相关文章

  1. Linux - 虚拟机中的三种网络连接,桥接、NAT、Host-only详解

    虚拟机中的三种网络连接 1.桥接 2.NAT 3.Host-only 桥接方便做实验,配置ip方便.可以和局域网中的其他机器进行通信,也可以和公网进行通信.缺点是会占用一个ip. NAT,可以和主机进 ...

  2. Springboot整合Elastic-Job(二)

    上文我们讲到Springboot整合Elastic-Job整合的demo,只是简单的实现了主要功能.本文在上文基础上,进行新的调整. 事件追踪 Elastic-Job提供了事件追踪功能,可通过事件订阅 ...

  3. Springboot整合Elastic-Job

    Elastic-Job是当当网的任务调度开源框架,有以下功能 分布式调度协调 弹性扩容缩容 失效转移 错过执行作业重触发 作业分片一致性,保证同一分片在分布式环境中仅一个执行实例 自诊断并修复分布式不 ...

  4. iOS UITableViewCell UITableVIewController 纯代码开发

    iOS UITableViewCell UITableVIewController 纯代码开发 <原创> .纯代码 自定义UITableViewCell 直接上代码 ////// #imp ...

  5. GitHub 多人协作开发 三种方式:

    GitHub 多人协作开发 三种方式: 一.Fork 方式 网上介绍比较多的方式(比较大型的开源项目,比如cocos2d-x) 开发者 fork 自己生成一个独立的分支,跟主分支完全独立,pull代码 ...

  6. YbSoftwareFactory 代码生成插件【二十五】:Razor视图中以全局方式调用后台方法输出页面代码的三种方法

    上一篇介绍了 MVC中实现动态自定义路由 的实现,本篇将介绍Razor视图中以全局方式调用后台方法输出页面代码的三种方法. 框架最新的升级实现了一个页面部件功能,其实就是通过后台方法查询数据库内容,把 ...

  7. App开发三种模式

    APP开发三种模式 现在App开发的模式包含以下三种: Native App 原生开发AppWeb App 网页AppHybrid App 混合原生和Web技术开发的App 详细介绍: http:// ...

  8. 关于Jenkins部署代码权限三种方案

    关于Jenkins部署代码权限三种方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.修改Jenkins进程用户为root [root@jenkins ~]# cat /etc ...

  9. Eclipse远程调试Java代码的三种方法

    Eclipse远程调试Java代码的三种方法, 第1种方法是用来调试已经启动的Java程序,Eclipse可以随时连接到远程Java程序进行调试, 第2种方法可以调试Java程序启动过程,但是Ecli ...

随机推荐

  1. javaweb-选课系统

    选课系统中用到了4个表,分别是classs.yonghu.teacher.student.在用户中存放管理员的信息name和password以及id,在另三个表中存放对应的数据如图: calss: t ...

  2. jeecg中自定义按钮时遇到的问题

  3. 20191121-4 Final发布用户使用报告

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/10064 队名:组长 组长:杨天宇 组员:罗杨美慧,王歆瑶,魏鑫,梅小雨 ...

  4. 我是如何一步步裹挟老板从.net 转到 java 阵营的

    我是如何一步步裹挟老板从.net 转到 java 阵营的 仅记录从 .net(C#) 转到 java 的一些心路历程 时间点跨度 2016 — 2017 一.前 xx 公司同事群的一次聊天 前公司同事 ...

  5. 用 Serverless 快速搭建个人相册网站

    日常生活中我们经常会拍摄一些视频.照片等,这些文件会占用比较多的存储空间.本文将介绍一种方法:利用 ThumbsUp 工具,结合 Serverless Framework 的 component 快速 ...

  6. 入门Grunt前端构建工具

    1. 全局安装 grunt:(倘若之前电脑安装过,则跳过此步骤) $ cnpm install -g grunt-cli 2. 作为项目的开发依赖(devDependencies)安装: (此步骤会自 ...

  7. java反射-- Field 用法实践

    java 反射是一种常用的技术手段, 通过加载类的字节码的方式来获取相关类的一些信息 比如成员变量, 成员方法等. Field 是什么呢? field 是一个类, 位于java.lang.reflec ...

  8. 自定义实现的ArrayList以及自定义实现的Iterator迭代器

    ArrayList的底层是长度可动态变化的数组,其适用于查找多,修改少的情况,原因是数组的元素的增加删除元素会涉及大量元素的移动,效率比较低,ArrayList中的元素可以重复,与插入时的顺序相同,可 ...

  9. CTO说|非容器化应用怎么玩多云?Kubernetes不管我们管啊

    Kubernetes已经成为容器编排系统的事实标准,是现在主流的跨云容器化应用操作系统. 但是,Kubernetes的目标并不是容器本身,而是承载其上的应用,本质上是为了解决(容器化)应用上云这个难题 ...

  10. 【UEFI】---基于UEFI编程的基本思路

    最近基于UEF在写代码的时候,发现由于粗心总是出现很多问题,而且都是一些小问题.虽然UEFI玩了挺久,但是也没梳理一下思路.借此机会整理一下: UEFI对复杂的BIOS代码做了很好的封装和模块化.  ...