SpringBoot-ElasticJob封装快速上手使用(分布式定时器)

elastic-job-spring-boot

qq交流群:812321371

1 简介

Elastic-Job是一个分布式调度解决方案,由两个相互独立的子项目Elastic-Job-LiteElastic-Job-Cloud组成。Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务。
基于quartz定时任务框架为基础的,因此具备quartz的大部分功能
使用zookeeper做协调,调度中心,更加轻量级
支持任务的分片
支持弹性扩容,可以水平扩展, 当任务再次运行时,会检查当前的服务器数量,重新分片,分片结束之后才会继续执行任务
失效转移,容错处理,当一台调度服务器宕机或者跟zookeeper断开连接之后,会立即停止作业,然后再去寻找其他空闲的调度服务器,来运行剩余的任务
提供运维界面,可以管理作业和注册中心。

1.1 使用场景

由于项目为微服务,单模块可能在两个实例以上的数量,定时器就会出现多实例同时执行的情况。
一般定时器缺少管理界面,无法监控定时器是否执行成功。
市面上常见的解决方案为定时器加锁的操作,或者采用第3方分布式定时器。
分布式定时器有多种方案,比如阿里内部的ScheduledX,当当网的Elastic job,个人开源的xxl-job等。

1.2 功能列表

  • 分布式调度协调
  • 弹性扩容缩容
  • 失效转移
  • 错过执行作业重触发
  • 作业分片一致性,保证同一分片在分布式环境中仅一个执行实例
  • 自诊断并修复分布式不稳定造成的问题
  • 支持并行调度
  • 支持作业生命周期操作
  • 丰富的作业类型
  • Spring整合以及命名空间提供
  • 运维平台

1.3 概念

分片:任务的分布式执行,需要将一个任务拆分为多个独立的任务项,然后由分布式的服务器分别执行某一个或几个分片项。
例如:有一个遍历数据库某张表的作业,现有2台服务器。为了快速的执行作业,那么每台服务器应执行作业的50%。 为满足此需求,可将作业分成2片,每台服务器执行1片。作业遍历数据的逻辑应为:服务器A遍历ID以奇数结尾的数据;服务器B遍历ID以偶数结尾的数据。 如果分成10片,则作业遍历数据的逻辑应为:每片分到的分片项应为ID%10,而服务器A被分配到分片项0,1,2,3,4;服务器B被分配到分片项5,6,7,8,9,直接的结果就是服务器A遍历ID0-4结尾的数据;服务器B遍历ID5-9结尾的数据。

历史轨迹:Elastic-Job提供了事件追踪功能,可通过事件订阅的方式处理调度过程的重要事件,用于查询、统计和监控。

1.4 封装elasticjob

由于当当网Elastic job处于1年间未更新阶段,相关jar处于可以使用阶段功能不全。考虑到使用场景为多项目使用,将elastic-job-lite-spring简单封装便于使用。

2.使用说明:

2.1 添加依赖

ps:实际version版本请使用最新版

<dependency>
  <groupId>com.purgeteam</groupId>
  <artifactId>elasticjob-spring-boot-starter</artifactId>
  <version>0.1.1.RELEASE</version>
</dependency>

2.2 配置

ps: 需要mysql,zookeeper支持,请提前搭建好。

配置bootstrap.yml或者application.yml

加入以下配置:

spring:
  elasticjob:
    datasource: # job需要的记录数据源
      url: jdbc:mysql://127.0.0.1:3306/batch_log?useUnicode=true&characterEncoding=utf-8&verifyServerCertificate=false&useSSL=false&requireSSL=false
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: Rtqw123OpnmER
    regCenter: # 注册中心
      serverList: 127.0.0.1:2181
      namespace: elasticJobDemo

2.3 定时器实现方法编写

创建定时器类(唯一不同的地方在于将@Scheduled改为实现SimpleJob接口即可)
定时器实现方法编写在execute方法里。

@Slf4j
@Component
public class MySimpleJob implements SimpleJob {

    //  @Scheduled(cron = "0 0/1 * * * ?")
    @Override
    public void execute(ShardingContext shardingContext) {
        log.info(String.format("Thread ID: %s, 作业分片总数: %s, " +
                        "当前分片项: %s.当前参数: %s," +
                        "作业名称: %s.作业自定义参数: %s",
                Thread.currentThread().getId(),
                shardingContext.getShardingTotalCount(),
                shardingContext.getShardingItem(),
                shardingContext.getShardingParameter(),
                shardingContext.getJobName(),
                shardingContext.getJobParameter()
        ));
        // 分片大致如下:根据配置的分片参数执行相应的逻辑
        switch (context.getShardingItem()) {
            case 0:
                // do something by sharding item 0
                break;
            case 1:
                // do something by sharding item 1
                break;
            case 2:
                // do something by sharding item 2
                break;
            // case n: ...
        }
    }
}
log:Thread ID: 66, 作业分片总数: 1, 当前分片项: 0.当前参数: Beijing,作业名称: PropertiesSimpleJob.作业自定义参数: test

2.4 配置定时器

2.4.1 创建Configuration类

ZookeeperRegistryCenterJobEventConfiguration注入。
创建JobScheduler @Bean(initMethod = "init")
mySimpleJobScheduler方法里先通过ElasticJobUtils#getLiteJobConfiguration获取LiteJobConfiguration对象。
创建SpringJobScheduler对象返回即可。

@Configuration
public class MyJobConfig {

    // job 名称
    private static final String JOB_NAME = "MySimpleJob";

    // 定时器cron参数
    private static final String CRON = "0 0/1 * * * ?";

    // 定时器分片
    private static final int SHARDING_TOTAL_COUNT = 1;

    // 分片参数
    private static final String SHARDING_ITEM_PARAMETERS = "0=Beijing,1=Shanghai,2=Guangzhou";

    // 自定义参数
    private static final String JOB_PARAMETERS = "parameter";

    @Resource
    private ZookeeperRegistryCenter regCenter;

    @Resource
    private JobEventConfiguration jobEventConfiguration;

    @Bean(initMethod = "init")
    public JobScheduler mySimpleJobScheduler(final MySimpleJob mySimpleJob) {

        LiteJobConfiguration liteJobConfiguration = ElasticJobUtils
                .getLiteJobConfiguration(mySimpleJob.getClass(), JOB_NAME, CRON,
                        SHARDING_TOTAL_COUNT, SHARDING_ITEM_PARAMETERS, JOB_PARAMETERS);
        // 参数:1.定时器实例,2.注册中心类,3.LiteJobConfiguration,
        //     3.历史轨迹(不需要可以省略)
        return new SpringJobScheduler(mySimpleJob, regCenter, liteJobConfiguration, jobEventConfiguration);
    }

}

ElasticJobUtils#getLiteJobConfiguration参数简介:

/**
     * 获取 {@link LiteJobConfiguration} 对象
     *
     * @param jobClass               定时器实现类
     * @param jobName                定时器名称
     * @param cron                   定时参数
     * @param shardingTotalCount     作业分片总数
     * @param shardingItemParameters 当前参数 可以为null
     * @param jobParameters          作业自定义参数 可以为null
     * @return {@link LiteJobConfiguration}
     */
  public static LiteJobConfiguration getLiteJobConfiguration(
      final Class<? extends SimpleJob> jobClass,
      final String jobName,
      final String cron,
      final int shardingTotalCount,
      final String shardingItemParameters,
      final String jobParameters) {
  ...
    return ...;
  }

2.4.2 简化Configuration类

当然也可以用下面的@Configuration实现简化,配置bootstrap.yml或者application.yml

spring:
  elasticjob:
    scheduled:
      jobConfigMap: // 为map集合
        PropertiesSimpleJob: // 定时器key名称
          jobName: PropertiesSimpleJob // job名称
          cron: 0 0/1 * * * ? // cron表达式
          shardingTotalCount: 2 // 分片数量
          shardingItemParameters: 0=123,1=332 // 分片参数
          jobParameters: test // 自定义参数

注入SpringJobSchedulerFactory,在propertiesSimpleJobScheduler方法里调用gerSpringJobScheduler方法即可。

@Configuration
public class PropertiesSimpleJobConfig {

    @Resource
    private SpringJobSchedulerFactory springJobSchedulerFactory;

    @Bean(initMethod = "init")
    public JobScheduler propertiesSimpleJobScheduler(final PropertiesSimpleJob job) {
        // 参数:1.定时器实例,2.配置名称,3.是否开启历史轨迹
        return springJobSchedulerFactory.getSpringJobScheduler(job,"PropertiesSimpleJob", true);
    }

}

2.4.3 注解方式配置(推荐方式)

ps:这个注解包含了上述方式,简化定时器注入。

继承SimpleJob实现方法execute

AnnotationSimpleJob类上加入注解@ElasticJobScheduler即可。
下面为完整注解。

@Slf4j
@ElasticJobScheduler(
        name = "AnnotationSimpleJob", // 定时器名称
        cron = "0/8 * * * * ?", // 定时器表达式
        shardingTotalCount = 1, // 作业分片总数 默认为1
        shardingItemParameters = "0=Beijing,1=Shanghai,2=Guangzhou",  // 分片序列号和参数用等号分隔 不需要参数可以不加
        jobParameters = "123", // 作业自定义参数 不需要参数可以不加
        isEvent = true // 是否开启数据记录 默认为true
)
public class AnnotationSimpleJob implements SimpleJob {

    @Override
    public void execute(ShardingContext shardingContext) {
        log.info(String.format("Thread ID: %s, 作业分片总数: %s, " +
                        "当前分片项: %s.当前参数: %s," +
                        "作业名称: %s.作业自定义参数: %s",
                Thread.currentThread().getId(),
                shardingContext.getShardingTotalCount(),
                shardingContext.getShardingItem(),
                shardingContext.getShardingParameter(),
                shardingContext.getJobName(),
                shardingContext.getJobParameter()
        ));
    }
}

总结

分布式job可以解决多个项目同一个定时器都执行的问题,配合elastic-job控制台可以直观监控定时器执行情况等。

示例代码地址:elastic-job-spring-boot

作者GitHub:
Purgeyao 欢迎关注
本文由博客一文多发平台 OpenWrite 发布!

原文地址:https://www.cnblogs.com/Purgeyao/p/11660660.html

时间: 2024-10-27 23:45:53

SpringBoot-ElasticJob封装快速上手使用(分布式定时器)的相关文章

SpringBoot快速上手——《一》:初始SpringBoot,实现入门级程序

初识SpringBoot,实现入门级程序 开发工具说明 : idea 可能有的同学很少使用idea,所以前两篇会比较多idea的截图操作! github源码:https://github.com/xivinChen/SpringBoot 1.搭建父工程 选中maven ,下一步填写组织信息,下一步知道finish.选择打开新窗口把父级工程中的src删除 2.创建第一个SpringBoot项目 这里选择Web,实质是引入了spring-boot-starter-web包 目录结构说明: src:

SpringBoot快速上手——《二》:SpringBoot集成SSM,实现增删改查功能

SpringBoot集成SSM,实现增删改查功能 github源码:https://github.com/xivinChen/SpringBoot 一.先介绍创建模块的另一种方式 1.点击Maven -> 勾选Create from archetype -> 选择 maven-archetype-quickstart 有时会需要点击 自动导入 2.工程目录 可以看到,这样创建的模块是相对干净的,需要我们手动的编写程序启动入口类.需要配置时还得创建配置文件.下一步见证. 3.完善模块 添加依赖,

快速上手JMeter

详情请交流  QQ  709639943 00.快速上手JMeter 00.Jmeter 00.2017年Java web开发工程师成长之路 00.R语言速成实战 00.R语言数据分析实战 00.Python+Django+Ansible Playbook自动化运维项目实战 00.Java深入微服务原理改造房产销售平台 00.Python3入门机器学习 经典算法与应用 00.老司机学python篇:第一季(基础速过.机器学习入门) 00.Python 从入门到精通 78节.2000多分钟.36小

Masonry介绍与使用实践:快速上手Autolayout

以上是纯手写代码所经历的关于页面布局的三个时期 在iphone1-iphone3gs时代 window的size固定为(320,480) 我们只需要简单计算一下相对位置就好了 在iphone4-iphone4s时代 苹果推出了retina屏 但是给了码农们非常大的福利:window的size不变 在iphone5-iphone5s时代 window的size变了(320,568) 这时autoresizingMask派上了用场(为啥这时候不用Autolayout? 因为还要支持ios5呗) 简单

MongoDB快速上手

1.  MongoDB简介 MongoDB是一个跨平台的基于Key_Value键值对形式保存数据的NoSQL文档类型数据库. NoSQL(not only sql)数据库,泛指非关系型数据库. 1.1 NoSQL数据库的特点 l  不需要预定义模式 不需要事先定义数据模式,预定义表结构.数据中的每条记录都可能有不同的属性和格式.当插入数据时,并不需要预先定义它们的模式. l  无共享架构 相对于将所有数据存储的存储区域网络中的全共享架构.NoSQL往往将数据划分后存储在各个本地服务器上.因为从本

Android快速上手指南(WIP)

JNI是java调用C/C++的一种封装技术,由JVM负责处理真实的JNI call. Java官方的文档 http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html Android平台的 http://developer.android.com/training/articles/perf-jni.html 快速上手的代码范例: https://android.googlesource.com/pl

我的新课--快速上手Jmeter性能测试工具正在筹划中

大家好,感谢大家一直以来对我的支持,新课快速上手Jmeter性能测试工具正在筹划中,大纲如下: 随着软件性能测试行业的崛起,各种性能测试工具也随之层出不穷,各具特色.同时,开源的趋势不可阻挡,如何使用开源免费的性能测试工具完成相关测试工作是很多企业正在考虑的问题.本套课程正是基于以上需求和现状,选择目前市面上最流行的开源性能测试工具Jmeter作为阐述对象,带领大家从零开始.步步为营,以掌握Jmeter的基本概念并熟练使用Jmeter进行测试为目标,快速而高效的学习和使用Jmeter.俗话说,授

学习Git---20分钟git快速上手

学习Git-----20分钟git快速上手 (图片已修复)在Git如日中天的今天,不懂git都不好意思跟人说自己是程序猿.你是不是早就跃跃欲试了,只是苦于没有借口(契机). 好吧,机会就在今天. 给我20分钟,是的,只要20分钟, 让你快速用上git. 我们废话不多说,直接来干货. 我们将会介绍以下几点: 一, 什么是git 二,使用git的一般开发流程 三,快速安装新建项目.holloworld. 开始: 一,什么是git. 阅读本文的前提是你知道或者用过至少一种源代码管理工具,比如:SVN,

快速上手如何使用FluentData

http://blog.itpub.net/29511780/viewspace-1194048/ 目录:  一.什么是ORM? 二.使用ORM的优势 三.使用ORM的缺点 四.NET下的ORM框架有哪些? 五.几种常用框架的比较 六.什么是FluentData? 七.快速上手如何使用FluentData? 八.提供资源下载 七.快速上手如何使用FluentData本文摘自:http://bbs.ibeifeng.com/read-htm-tid-66379.html 下面我将一一举例向大家介绍