当前位置: 首页 > news >正文

为什么要引入分布式任务调度系统?

本文收录于JavaStarter ,里面有我完整的Java系列文章,学习或面试都可以看看

本文将介绍分布式任务调度系统:xxl-job,开源地址如下:

码云地址:https://gitee.com/xuxueli0323/xxl-job

文档地址:https://www.xuxueli.com/xxl-job/

(一)定时任务的场景

在开发中,定时任务是一种十分常见的应用场景,比如每天晚上12点同步数据,又或者每隔一个小时拉取一次数据。

在Java中,实现定时任务的方式有很多,最简单的在线程中通过Thread.sleep睡眠线程,或者采用SpringBoot中的@Schedule注解,又或者采用定时线程池ScheduledExecutorService来实现。

(二)上面的定时任务会有什么问题?

在单机环境下,上面的这种定时任务实现方式问题主要有一个,无法进行管理,没有容错机制。

但是在集群环境下,如果不对代码作控制,就会导致集群的每一台机器都会执行一次定时任务。

常见的解决方式,我通过配置文件进行控制,只让定时任务在某一台机器上执行,如果项目比较小,就几台机器组成的集群环境,这样的方式确实可以,只不过在任务的管理上需要想办法解决。

如果是一个很庞大的分布式微服务系统,可能会有成千上万个定时任务,那上面的方法就不合理了。因此许多互联网公司会采用分布式任务调度系统,主要为了实现高可用、容错管理、负载均衡、管理机制等功能,我目前所在公司使用的是xxl-job作为分布式任务调度平台。

(三)xxl-job的使用

xxl-job的一大优势就是使用简单,学习成本低,xxl-job作者已经给出了很详细的使用说明,下面我们就通过源码直接来跑一下。

3.1 初始化调度数据库

git上clone的项目中保存了初始化sql脚本,位置在:

/xxl-job/doc/db/tables_xxl_job.sql

执行完毕后会在数据库中新建库以及表结构。

3.2 修改配置

修改主配置文件:

/xxl-job/xxl-job-admin/src/main/resources/application.properties

主要修改jdbc的连接信息,以及报警邮件,xxl-job支持通过邮件报警的方式。

3.3 运行项目

直接运行xxl-job-admin中的XxlJobAdminApplication,正常启动后访问http://localhost:8080/xxl-job-admin,输入用户名密码:admin/123456,然后就能看到任务调度中心页面了

到这里为止,xxl-job的管理平台已经搭建完成,接下来展示客户端使用xxl-job的案例。xxl-job支持多种执行方式,我这里演示Java Bean的使用。其余的可看官方提供的技术文档。

3.4 配置执行器

执行器管理页面点击新增执行器:

AppName: 是每个执行器集群的唯一标示AppName, 执行器会周期性以AppName为对象进行自动注册。可通过该配置自动发现注册成功的执行器, 供任务调度时使用;
名称: 执行器的名称, 因为AppName限制字母数字等组成,可读性不强, 名称为了提高执行器的可读性;
排序: 执行器的排序, 系统中需要执行器的地方,如任务新增, 将会按照该排序读取可用的执行器列表;
注册方式:调度中心获取执行器地址的方式;
    自动注册:执行器自动进行执行器注册,调度中心通过底层注册表可以动态发现执行器机器地址;
    手动录入:人工手动录入执行器的地址信息,多地址逗号分隔,供调度中心使用;
机器地址:"注册方式""手动录入"时有效,支持人工维护执行器的地址信息;

我这里选择手动录入,并且自己输入执行器的地址,ip是本机ip,端口选择一个未使用过的端口。

3.5 编写客户端代码

接下来编写客户端的代码,在xxl开源项目中,已经有springboot的demo,我们自己写一个。

第一步引入依赖:

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>${project.parent.version}</version>
</dependency>

这里的version填写最新的稳定版本,因为我在xxljob的开源项目中新建了一个module进行测试,因此直接用父项目版本了。

第二步编写配置文件:

server.port=8081

xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=

xxl.job.executor.appname=test-xxl-job
xxl.job.executor.address=
xxl.job.executor.ip=172.18.2.49
xxl.job.executor.port=8999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=30

几个注意点:

xxl.job.admin.addresses是管理平台的地址

xxl.job.executor.appname是我们上面的执行器appname

xxl.job.executor.address不填的话就是xxl.job.executor.ip:xxl.job.executor.port

其他的就按照执行器配置的填。

第三步编写配置类

@Configuration
public class XxlConfig {
    private Logger logger = LoggerFactory.getLogger(XxlConfig.class);

    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;

    @Value("${xxl.job.accessToken}")
    private String accessToken;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @Value("${xxl.job.executor.address}")
    private String address;

    @Value("${xxl.job.executor.ip}")
    private String ip;

    @Value("${xxl.job.executor.port}")
    private int port;

    @Value("${xxl.job.executor.logpath}")
    private String logPath;

    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
        return xxlJobSpringExecutor;
    }
}

第四步编写demo代码:

@Component
public class DemoJobHandler {

    @XxlJob("demoJobHandler")
    public void demoJobHandler(){
        System.out.println("执行定时任务");
        XxlJobHelper.log("执行定时任务");
    }
}

通过@XxlJob(“demoJobHandler”),指定任务的名称。

3.5 配置任务

代码写好了,接下来配置具体的任务了,进管理平台的任务管理,在test执行器下新建一个任务,简单如下配置:

Cron配置了每10s执行一次,配置任务完成后启动任务,定时Job就开始工作了,通过日志可以查看是否执行成功。

(四)xxl-job集群下的使用

既然被称为分布式任务调度平台,xxl-job如何体现分布式场景下的任务调度呢?在任务配置的高级配置中,提供了多种路由策略:

我现在选择轮询,然后修改一下执行器的配置,加入两个地址:

http://172.18.2.49:8999,http://172.18.2.49:8998

同时将测试项目启动两个,两者的配置文件分别为:

#第一个项目
server.port=8081
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=
xxl.job.executor.appname=test-xxl-job
xxl.job.executor.address=
xxl.job.executor.ip=172.18.2.49
xxl.job.executor.port=8999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=30

#第二个项目
server.port=8082
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=
xxl.job.executor.appname=test-xxl-job
xxl.job.executor.address=
xxl.job.executor.ip=172.18.2.49
xxl.job.executor.port=8998
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=30

再启动任务后,会发现定时任务会在两个项目中轮询的执行:


除了轮询之外,像故障转移、忙碌转移策略可以实现容错,一致性哈希可以保证同一个任务只在一台机器上执行。

(五)总结

目前分布式任务调度的开源框架有很多,xxl-job是最常用的,功能确实很完善,同时完全开源。也难怪大量互联网企业在使用它。我是鱼仔,我们下期再见!

相关文章:

  • 为什么说datax是目前最好的异构数据源数据交换工具
  • Java常用关键字:this、super、final、static、访问修饰符
  • JAVA UUID 生成唯一标识
  • 网络开发的最强大框架:Netty快速入门
  • 适配器模式详解与应用
  • 树莓派 - 使用须知
  • 粘包和半包有了解过吗?netty是如何解决这个问题的
  • 云计算与SOA之我见
  • 迭代器模式:理解与实践
  • [转]MySQL排序原理与案例分析
  • 深入浅出CMS垃圾收集器
  • php.ini中的session配置说明
  • 如何上传自己的jar包到maven中央仓库(2021最新版)
  • ElasticSearch聚合查询Restful语法和JavaApi详解(基于ES7.6)
  • 《偷影子的人》
  • JavaScript学习总结——原型
  • Java教程_软件开发基础
  • Java-详解HashMap
  • java正则表式的使用
  • spring boot 整合mybatis 无法输出sql的问题
  • 不用申请服务号就可以开发微信支付/支付宝/QQ钱包支付!附:直接可用的代码+demo...
  • 近期前端发展计划
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端学习笔记之观察者模式
  • AI算硅基生命吗,为什么?
  • ​如何防止网络攻击?
  • # Panda3d 碰撞检测系统介绍
  • #### go map 底层结构 ####
  • #pragma预处理命令
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (分类)KNN算法- 参数调优
  • (南京观海微电子)——COF介绍
  • (三) diretfbrc详解
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)C#调用WebService 基础
  • .a文件和.so文件
  • .gitignore
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Core跨平台微服务学习资源
  • .net mvc 获取url中controller和action
  • .Net mvc总结
  • .net 生成二级域名
  • .NET企业级应用架构设计系列之技术选型
  • .Net中的设计模式——Factory Method模式
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • [Angularjs]asp.net mvc+angularjs+web api单页应用
  • [C++]类和对象【下】
  • [caffe(二)]Python加载训练caffe模型并进行测试1
  • [CISCN2019 华东南赛区]Web4
  • [Django 0-1] Core.Checks 模块
  • [FFmpeg学习]从视频中获取图片
  • [flask] flask的基本介绍、flask快速搭建项目并运行