本文以在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. C#实现快速查找(递归,非递归)

    原文件: http://pan.baidu.com/share/link?shareid=2838344856&uk=3912660076 我英语很烂...哎,我正在努力... 效果图:

  2. Netty 源码解析(四): Netty 的 ChannelPipeline

    今天是猿灯塔“365篇原创计划”第四篇. 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty 源码解析(一): 开始 Netty 源码解析(二): Netty 的 Channel Netty ...

  3. 从0开始,手把手教你使用React开发答题App

    项目演示地址 项目演示地址 项目源码 项目源码 其他版本教程 Vue版本 小程序版本 项目代码结构 前言 React 框架的优雅不言而喻,组件化的编程思想使得React框架开发的项目代码简洁,易懂,但 ...

  4. 输入Javac提示不是内部或外部命令怎么办

    首先,我们在电脑上面找到此电脑, 然后右键点击,选择属性.   在属性中,我们找到高级系统设置,点击打开,如图示.   然后在系统设置中,我们可以找到启动和鼓掌恢复,然后点击环境变量,点击打开.   ...

  5. ASP.NET Core策略授权和 ABP 授权

    目录 ASP.NET Core 中的策略授权 策略 定义一个 Controller 设定权限 定义策略 存储用户信息 标记访问权限 认证:Token 凭据 颁发登录凭据 自定义授权 IAuthoriz ...

  6. 创建MongoDB副本集教程

    今天有时间搞了一下mongoDB的副本集,遇到好多坑,写下此文,方便日后查阅! 本教程是在windows环境下安装测试的(我是本机一台 + 两台虚拟机) 本机:10.53.8.159 虚拟机一:10. ...

  7. bzoj1787[Ahoi2008]Meet 紧急集合&bzoj1832[AHOI2008]聚会

    bzoj1787[Ahoi2008]Meet 紧急集合 bzoj1832[AHOI2008]聚会 题意: 给个树,每次给三个点,求与这三个点距离最小的点. 题解: 倍增求出两两之间的LCA后,比较容易 ...

  8. Java 分布式任务调度平台:PowerJob 快速开始+配置详解

    本文适合有 Java 基础知识的人群 作者:HelloGitHub-Salieri 引言 HelloGitHub 推出的<讲解开源项目>系列. 项目地址: https://github.c ...

  9. TCP 进阶

    转自: https://www.cnblogs.com/caoyusongnet/p/9087633.html 一. 端口号 标准的端口号由 Internet 号码分配机构(IANA)分配.这组数字被 ...

  10. day7 python字符串的操作及方法

    1.字符串 1.1 字符串的操作 # 1.字符串的拼接 strvar = "我爱" + "中国" # 2.字符串的重复 strvar = "今天下午2 ...