本文以在SpringBoot下集成ElasticJob的方式对其进行浅析,仅仅是简单使用,不涉及源码级别研究。

事先必备:

注册中心——zookeeper

简略结构:

代码目录结构:

├─.idea
└─src
└─main
├─java
│ └─com
│ └─sakura
│ ├─configuration --SpringJobScheduler、ZookeeperRegistryCenter
│ ├─job
│ │ ├─jobEventConfig --Job事件监听器
│ │ └─jobListener --Job执行监听器
│ └─properties --Zookeeper、Job的配置信息
└─resources --Zookeeper、Job的配置信息

初始化注册中心:

@Configuration
@Slf4j
public class ZookeeperRegistry { @Bean(name = "registryCenter", initMethod = "init")
public ZookeeperRegistryCenter registryCenter(ZookeeperRegistryProperties registryProperties) {
ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(
registryProperties.getServerLists(), registryProperties.getNamespace());
zookeeperConfiguration.setDigest(registryProperties.getDigest());
zookeeperConfiguration.setBaseSleepTimeMilliseconds(registryProperties.getBaseSleepTimeMilliseconds());
zookeeperConfiguration.setConnectionTimeoutMilliseconds(registryProperties.getConnectionTimeoutMilliseconds());
zookeeperConfiguration.setMaxRetries(registryProperties.getMaxRetries());
zookeeperConfiguration.setMaxSleepTimeMilliseconds(registryProperties.getMaxSleepTimeMilliseconds());
zookeeperConfiguration.setSessionTimeoutMilliseconds(zookeeperConfiguration.getSessionTimeoutMilliseconds());
log.info("elasticJob注册中心——Zookeeper初始化成功。serverLists={}。nameSpace={}", registryProperties.getServerLists(), registryProperties.getNamespace());
return new ZookeeperRegistryCenter(zookeeperConfiguration);
}
}

定义Job(以SimpleJob为例):

@Slf4j
@Component
public class MySimpleJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
log.info("------开始执行定时任务------");
log.info("jobName:{}", shardingContext.getJobName());
log.info("taskId:{}", shardingContext.getTaskId());
}
}

初始化SpringJobScheduler:

@Configuration
@Data
public class SpringJobSchedulerInit {
private final ZookeeperRegistryCenter registryCenter;
private final ZookeeperRegistryProperties zookeeperRegistryProperties;
private final SimpleJobProperties simpleJobProperties;
private final ElasticJob mySimpleJob;
private final JobEventConfiguration jobEventConfiguration; @Bean(initMethod = "init")
public SpringJobScheduler springJobScheduler() {
return new SpringJobScheduler(mySimpleJob, registryCenter, getLiteJobConfiguration(),
          //Job事件追踪,非必填
jobEventConfiguration,
          //Job执行监听器,非必填
new MySimpleJobListener());
} public LiteJobConfiguration getLiteJobConfiguration() { JobCoreConfiguration jobCoreConfiguration = JobCoreConfiguration.newBuilder(simpleJobProperties.getJobName(), simpleJobProperties.getCron()
, simpleJobProperties.getShardingTotalCount())
.failover(simpleJobProperties.isFailover())
.jobParameter(simpleJobProperties.getJobParameter())
.misfire(true)
.shardingItemParameters(simpleJobProperties.getShardingItemParameters())
.build();
JobTypeConfiguration jobTypeConfiguration = new SimpleJobConfiguration(jobCoreConfiguration, MySimpleJob.class.getName()); return LiteJobConfiguration.newBuilder(jobTypeConfiguration)
.jobShardingStrategyClass(simpleJobProperties.getJobShardingStrategyClass())
.maxTimeDiffSeconds(simpleJobProperties.getMaxTimeDiffSeconds())
.monitorExecution(simpleJobProperties.isMonitorExecution())
.monitorPort(simpleJobProperties.getMonitorPort())
.maxTimeDiffSeconds(simpleJobProperties.getMaxTimeDiffSeconds())
//是否要用本地的配置覆盖掉远程的ElasticJob配置
.overwrite(false)
.build();
}
}

Job事件追踪——存储到数据库:

@Configuration
@Slf4j
@Data
public class JobEventConfig {
private final DataSource dataSource; @Bean
public JobEventConfiguration jobEventConfiguration() {
return new JobEventRdbConfiguration(dataSource);
}
}

Job执行监听器:

@Slf4j
public class MySimpleJobListener implements ElasticJobListener {
@Override
public void beforeJobExecuted(ShardingContexts shardingContexts) {
log.info("Job执行之前:{}", ReflectionToStringBuilder.toString(shardingContexts));
} @Override
public void afterJobExecuted(ShardingContexts shardingContexts) {
log.info("Job执行之后:{}", ReflectionToStringBuilder.toString(shardingContexts));
}
}

properties配置信息:

@ConfigurationProperties(prefix = "simple.job")
@Data
public class SimpleJobProperties {
  //执行Job的cron表达式
private String cron;
  //Job分片总数
private int shardingTotalCount;
  //分片序列号和个性化参数对照表
  //分片序列号和参数用等号分隔,多个键值对用逗号分隔
  //分片序列号从0开始,不可大于或等于Job分片总数
  //如:0=a,1=b,2=c
   private String shardingItemParameters;
  //Job自定义参数
private String jobParameter;
  //是否开启失效转移。
  //只有对monitorExecution的情况下才可以开启失效转移。
  private boolean failover;
  //监控Job执行时状态。每次Job执行时间和间隔时间均非常短的情况,建议不监控作业运行时状态以提升效率, 因为是瞬时状态, 所以无必要监控。
private boolean monitorExecution;
  //作业辅助监控端口
private int monitorPort;
  //最大容忍的本机与注册中心的时间误差秒数,如果时间误差超过配置秒数则作业启动时将抛异常。
  //设置为-1表示不进行检查。
   private int maxTimeDiffSeconds;
  //作业分片策略实现类全路径
private String jobShardingStrategyClass;
  //Job的名称
private String jobName;
}
@ConfigurationProperties(prefix = "elastic.job.zk")
@Data
public class ZookeeperRegistryProperties {
  //服务地址,ip:port,多个地址用逗号分隔
private String serverLists;
  //命名空间
private String namespace;
  //最大重试次数
private int maxRetries = ;
  //连接超时时间,毫秒
private int connectionTimeoutMilliseconds = ;
  //会话超时时间,毫秒
private int sessionTimeoutMilliseconds = ;
  //等待重试的间隔时间的初始值,毫秒
private int baseSleepTimeMilliseconds = ;
  //等待重试的间隔时间的最大值,毫秒
private int maxSleepTimeMilliseconds = ;
  //连接zk的权限令牌,缺省为不需要权限验证。
private String digest = ""; }
server.port=
spring.application.name=elasticJobTest #ZK
elastic.job.zk.serverLists=192.168.204.140:,192.168.204.141:,192.168.204.142:
elastic.job.zk.namespace=elastic-job #ElasticJob
simple.job.jobName=simpleJob
simple.job.cron=/ * * * * ?
simple.job.shardingTotalCount=
simple.job.shardingItemParameters==beijing,=shanghai,=changchun
simple.job.job-parameter=source1=public,source2=private
simple.job.failover=true
simple.job.monitor-execution=true
simple.job.monitor-port=
simple.job.max-time-diff-seconds=-
simple.job.job-sharding-strategy-class=com.dangdang.ddframe.job.lite.api.strategy.impl.AverageAllocationJobShardingStrategy spring.datasource.url=jdbc:mysql://localhost:3306/elasticjob?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=

pom.xml依赖:

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- elastic-job dependency -->
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-core</artifactId>
<version>2.1.</version>
</dependency>
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
<version>2.1.</version>
</dependency>
</dependencies>

启动类:

@SpringBootApplication(scanBasePackages = {"com.sakura.*"})
@EnableConfigurationProperties(value = {ZookeeperRegistryProperties.class, SimpleJobProperties.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}

分片:

ElasticJob提供了三种分片策略。

  1. 基于平均分配算法的分片策略。如果分片不能整除, 则不能整除的多余分片将依次追加到序号小的服务器。
    1. 如果有3台服务器, 分成9片, 则每台服务器分到的分片是: 1=[0,1,2], 2=[3,4,5], 3=[6,7,8]。
    2. 如果有3台服务器, 分成8片, 则每台服务器分到的分片是: 1=[0,1,6], 2=[2,3,7], 3=[4,5]。
    3. 如果有3台服务器, 分成10片, 则每台服务器分到的分片是: 1=[0,1,2,9], 2=[3,4,5], 3=[6,7,8]。
  2. 根据作业名的哈希值奇偶数决定IP升降序算法的分片策略。作业名的哈希值为奇数则IP升序。作业名的哈希值为偶数则IP降序。
    1. 如果有3台服务器, 分成2片, 作业名称的哈希值为奇数, 则每台服务器分到的分片是: 1=[0], 2=[1], 3=[]。
    2. 如果有3台服务器, 分成2片, 作业名称的哈希值为偶数, 则每台服务器分到的分片是: 3=[0], 2=[1], 1=[]。
  3. 根据作业名的哈希值对服务器列表进行轮转的分片策略。

为什么要进行分片:

将一个任务拆分为多个可以并行执行的子任务(分片),每个服务器负责处理一定量的子任务,提高效率。

在本实例代码中一共有三个服务器,进行了三个分片,所以在执行Job时会看到如下的日志打印:

------开始执行定时任务------JobParameter:source1=public,source2=private,ShardingItem:,ShardingParameter:beijing
------开始执行定时任务------JobParameter:source1=public,source2=private,ShardingItem:,ShardingParameter:changchun
------开始执行定时任务------JobParameter:source1=public,source2=private,ShardingItem:,ShardingParameter:shanghai

可以根据Job的ShardingParameter不同做区分,让其处理不同的子任务。

ElasticJob和SpringBoot的更多相关文章

  1. SpringBoot定时任务 - 什么是ElasticJob?如何集成ElasticJob实现分布式任务调度?

    前文展示quartz实现基于数据库的分布式任务管理和job生命周期的控制,那在分布式场景下如何解决弹性调度.资源管控.以及作业治理等呢?针对这些功能前当当团队开发了ElasticJob,2020 年 ...

  2. Springboot整合Elastic-Job(二)

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

  3. Springboot整合Elastic-Job

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

  4. SpringBoot使用Elastic-Job

    本文介绍SpringBoot整合Elastic-Job分布式调度任务(简单任务). 1.有关Elastic-Job Elastic-Job是当当网开源的分布式任务调度解决方案,是业内使用较多的分布式调 ...

  5. elastic-job 分布式定时任务框架 在 SpringBoot 中如何使用(一)初始化任务并定时执行

    第一篇需要实现一个最简单的需求:某个任务定时执行,多台机子只让其中一台机子执行任务 一.安装 分布式应用程序协调服务 zookeeper,安装步骤在链接里面 Linux(Centos7)下安装 zoo ...

  6. elasticjob学习一:simplejob初识和springboot整合

    Elastic-Job是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成. Elastic-Job-Lite定位为轻量级无中心化解 ...

  7. springboot整合elasticJob实战(纯代码开发三种任务类型用法)以及分片系统,事件追踪详解

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

  8. elastic-job集成到springboot教程,和它的一个异常处理办法:Sharding item parameters '1' format error, should be int=xx,int=xx

    先说这个Sharding item parameters '1' format error, should be int=xx,int=xx异常吧,这是在做动态添加调度任务的时候出现的,网上找了一会没 ...

  9. SpringBoot整合Elastic-job(详细)

    一 作业分片1.分片概念作业分片是指任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的应用实例分别执行某一个或几个分片项.例如:Elastic-Job快速入门中文件备份的例子,现有 ...

随机推荐

  1. 'printf' Function

    printf is not part of the C language; there is no input or output defined in C itself. printf is jus ...

  2. python数据类型的72变

    输入数据的类型 input函数接收的数据默认为字符串类型 转换函数 通过转换函数实现接收其他类型的数据 1.接收整数:字符串→整型数据: int("整数格式的字符串") 2.接收小 ...

  3. Python3笔记019 - 4.4 字典

    第4章 序列的应用 python的数据类型分为:空类型.布尔类型.数字类型.字节类型.字符串类型.元组类型.列表类型.字典类型.集合类型 在python中序列是一块用于存放多个值的连续内存空间. py ...

  4. Vs Code推荐安装插件

    前言: Visual Studio Code是一个轻量级但功能强大的源代码编辑器,轻量级指的是下载下来的Vs Code其实就是一个简单的编辑器,强大指的是支持多种语言的环境插件拓展,也正是因为这种支持 ...

  5. python入门009

    目录 四.列表 1.定义:在[]内,用逗号分隔开多个任意数据类型的值 2.类型转换:但凡能被for循环遍历的数据类型都可以传给list()转换成列表类型,list()会跟for循环一样遍历出数据类型中 ...

  6. AcWing 93. 递归实现组合型枚举

    AcWing 93. 递归实现组合型枚举 原题链接 从 1~n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案. 输入格式 两个整数 n,m ,在同一行用空格隔开. 输出格式 按照从小到大的 ...

  7. ShaderLab-坐标转换

    观察空间就是相机的空间 投影矩阵本质就是对x.y.z分量进行不同程度的缩放(z还做了平移),结果就是视锥体近切面远切面变成正方形.视锥体的中心在(0,0). (对于正交相机,这一步已经得到了立方体) ...

  8. 小白从零开始阿里云部署react项目+node服务接口(二:node服务+web)

    我们用极简的方式来创建服务,没有任何附加功能 1 新建一个server文件夹 2 使用npm init 或者yarn init  一路enter 3  yarn add  express cors  ...

  9. Burp Suite Report - 报告功能

    1. 通过点击Host选择不同的颜色,可以设置严重性: 2.生成网页版应用分析报告:选中所有条目->右击网址,保存所有选中项目,存储格式为html.

  10. JavaWeb基础(day15)( http + tomcat + servlet + 响应)

    HTTP+Tomcat+Servlet+响应 HTTP HTTP  超文本传输协议(Hyper Text  Transfer  Protocol  ),一种网络协议. 协议的组成和过程 HTTP协议由 ...