美文网首页分布式
xxl-job分布式任务调度框架体验

xxl-job分布式任务调度框架体验

作者: 文景大大 | 来源:发表于2023-01-19 15:10 被阅读0次

    一、xxl-job是什么

    xxl-job是一个分布式任务调度平台,其核心特点就是简单、能快速上手、轻量级、易扩展。在如今的分布式场景中,已经成为主流的任务调度框架。

    二、xxl-job快速上手体验

    2.1 环境配置

    该步骤在官方中文文档上都有详细介绍,略过~

    2.2 配置和部署调度中心

    按照文档将xxl-job-admin打包部署到对应的服务器上即可。

    2.3 配置和部署执行器

    这里就以github来下来的项目中的xxl-job-executor-sample-springboot为例进行演示。该项目需要包含如下三个要素才能正常注册到调度中心:

    1. 引入核心依赖包

      <!-- xxl-job-core -->
      <dependency>
          <groupId>com.xuxueli</groupId>
          <artifactId>xxl-job-core</artifactId>
          <version>${project.parent.version}</version>
      </dependency>
      
    2. 修改执行器配置

      # web port
      server.port=8081
      # log config
      logging.config=classpath:logback.xml
      # [选填]调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
      xxl.job.admin.addresses=http://x.x.x.x:8080/xxl-job-admin/
      # [选填]执行器通讯TOKEN:非空时启用;
      xxl.job.accessToken=
      # [选填]执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
      xxl.job.executor.appname=zx-executor
      # [选填]执行器注册:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
      xxl.job.executor.address=
      # [选填]执行器IP:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
      xxl.job.executor.ip=
      # [选填]执行器端口号:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
      xxl.job.executor.port=9998
      # [选填]执行器运行日志文件存储磁盘路径:需要对该路径拥有读写权限;为空则使用默认路径;
      xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
      # [选填]执行器日志文件保存天数:过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
      xxl.job.executor.logretentiondays=30
      
    3. 注册执行器组件

      参考XxlJobConfig.java中的代码,将如上配置文件中的内容注册到Spring的Bean中。

    最后将该项目打包部署到对应的服务器上即可。

    2.4 调度中心执行器配置

    默认情况下,我们如上的zx-executor并不会自动注册并展示在调度中心admin控制台的“执行器管理”里面,需要我们手动创建一下:

    新建执行器

    如果此时执行器不在线的话,OnLine机器地址就展示无,如果在线的话就能展示具体的执行器IP地址了。因为我们是自动注册,所以执行器和调度中心之间会有心跳,按照官方文档的描述,默认是30秒,如果持续90秒没有收到执行器的心跳,调度中心就会将该执行器移除。当然,如果执行器是主动注销的,会立即上报给调度中心。

    2.5 调度中心任务配置

    默认情况下,我们在执行器中声明和定义的任务也不会自动注册和展示到调度中心admin控制台的“任务管理”里面,需要我们手动创建一下。

    新建任务

    具体的参数信息可以查看官方文档,有比较详细的描述和说明。在创建完毕后,该任务是处于STOP状态,需要将其改为”启动状态“,才会按照设置的调度信息进行任务的调度。

    三、特性介绍

    1. 简单:支持通过Web页面对任务进行CRUD操作,可以简单上手;

    2. 动态:支持动态修改任务状态,切换启动和停止,还可以终止正在运行中的任务,即时生效;

    3. 调度中心HA:调度中心支持集群部署,多个调度中心连接同一个数据库即可,靠DB锁来实现调度的一致性;

    4. 执行器HA:同一个执行器支持集群部署,保持各自设置的appname相同即可,支持分片执行;

    5. 注册中心:执行器会周期性地自动注册任务,调度中心则会自动发现任务并按照设定的调度参数执行,同时,也支持手动录入执行器地址;

      执行器的自动注册不是指执行器会自动出现在“执行器管理”的列表里面,相反执行器需要管理员自己手动创建,自动注册指的是执行器里面Online机器地址会自动注册。

      如果我们在创建执行器的时候没有选择“自动注册”,而是选择手动录入机器地址,那么就不会有心跳自动检测,即是执行器关闭或者有新的执行器注册上来都不会自动注册,更新到Online机器地址中;

      同样的,执行器里面的任务也是需要管理员手动创建的,并非可以自动展示在执行器的任务列表里面。其实这也是为了安全考虑,只有管理员手动确认新建的任务才能得到执行。

    6. 弹性扩缩容:一旦有新的执行器上线或者下线,下次调度将会重新分配任务;

    7. 触发策略:提供丰富的任务触发策略,包括Cron触发、固定间隔触发、固定延时触发、API事件触发、人工触发、父子任务触发;

    8. 调度过期策略:调度中心错过调度时间的补偿处理策略,包括忽略、立即补偿触发一次等;

    9. 阻塞处理策略:调度过于密集执行器来不及处理时的策略,包括:

      1. 单机串行:调度请求进入单机执行器后,无论执行器当前是否忙碌,调度请求进入FIFO队列,等待穿行执行;
      2. 丢弃后续调度:调度请求进入单机执行器后,发现执行器正在工作,那么本次请求会被丢弃标记为调度失败;
      3. 覆盖之前调度:调度请求进入单机执行器后,发现执行器正在工作,那么会终止正在执行的任务,清空队列,马上运行当前请求的任务;
    10. 任务超时控制:支持自定义任务超时时间,任务运行超时就会主动中断任务;

    11. 任务失败重试:支持自定义任务失败重试次数,当任务失败时将会按照预设的失败重试次数主动进行重试;其中分片任务支持分片粒度的失败重试;

    12. 任务失败告警:默认提供邮件方式失败告警,同时预留扩展接口,可方便的扩展短信、钉钉等告警方式;

    13. 路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;这是明显由于Quartz的特性;

    14. 分片广播任务:执行器集群部署时,任务路由策略选择”分片广播”情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;

      分片任务的好处就是可以把一个n个相同的任务分给同一个执行器中的不同单机执行,从而提升并发度,提高任务的执行效率。我们将springboot示例项目在项目里面复制一份,修改端口号并改为maven子项目后启动,从而就得到一个执行器集群。

      然后在管理端新建一个分片广播任务:

      新建一个分片广播任务

      然后我们手动执行一次后,会发现该执行器集群中的两台单机都执行了一次shardingJobHandler任务:

      分片广播任务的执行结果

      它们对应的执行日志如下:

        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[59]-[xxl-job, JobThread-44-1674195417203] 分片参数:当前分片序号 = 0, 总分片数 = 2
        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[64]-[xxl-job, JobThread-44-1674195417203] 第 0 片, 命中分片开始处理
        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[66]-[xxl-job, JobThread-44-1674195417203] 第 1 片, 忽略
    
        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[59]-[xxl-job, JobThread-44-1674195417341] 分片参数:当前分片序号 = 1, 总分片数 = 2
        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[66]-[xxl-job, JobThread-44-1674195417341] 第 0 片, 忽略
        2023-01-20 14:16:57 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#shardingJobHandler]-[64]-[xxl-job, JobThread-44-1674195417341] 第 1 片, 命中分片开始处理
    

    分片任务还有另外一种形式,就是在管理端创建多个配置相同的任务,路由策略都是第一个空闲的执行器执行,然后JobHandler都设置成为一样的,只是执行参数设置为不同的参数段,从而使得各个单机执行器按照自己的参数段各自执行各自的任务。

    1. 动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度;

    2. 故障转移:任务路由策略选择”故障转移”情况下,如果执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求;

    3. 任务进度监控:支持实时监控任务进度;

    4. Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;

    5. GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯;--待实验

    6. 脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS、PHP、PowerShell等类型脚本;--待实验

    7. 命令行任务:原生提供通用命令行任务Handler(Bean任务,”CommandJobHandler”);业务方只需要提供命令行即可;--待实验

    8. 任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;--待实验

    9. 一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;

    10. 自定义任务参数:支持在线配置调度任务入参,即时生效;--待实验

    11. 调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;

    12. 数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;

    13. 邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;

    14. 推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;

    15. 运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;

    16. 全异步:任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰,理论上支持任意时长任务的运行;

    17. 跨语言:调度中心与执行器提供语言无关的 RESTful API 服务,第三方任意语言可据此对接调度中心或者实现执行器。除此之外,还提供了 “多任务模式”和“httpJobHandler”等其他跨语言方案;

    18. 国际化:调度中心支持国际化设置,提供中文、英文两种可选语言,默认为中文;

    19. 容器化:提供官方docker镜像,并实时更新推送dockerhub,进一步实现产品开箱即用;

    20. 线程池隔离:调度线程池进行隔离拆分,慢任务自动降级进入”Slow”线程池,避免耗尽调度线程,提高系统稳定性;

    21. 用户管理:支持在线管理系统用户,存在管理员、普通用户两种角色;

    22. 权限控制:执行器维度进行权限控制,管理员拥有全量权限,普通用户需要分配执行器权限后才允许相关操作;

    四、架构分析

    xxl-job架构图

    分为调度中心和执行器两种角色:

    • 调度中心被抽象为一个只负责调度的平台,其本身不承担任何任务相关的业务逻辑,只负责发起调度请求;
    • 执行器是具体执行业务逻辑任务的承担者;

    这两种角色都可以HA,集群方式部署,如此调度和任务两部分就可以解耦,提高了系统的整体稳定性和可扩展性。

    五、和Quartz的区别

    同样是集群环境下,Quartz具有如下的缺点:

    • Quartz只能通过API的方式操作任务,不够人性化;而xxl-job则还可以提供管理端界面操作的形式,使用上更方便;
    • Quartz会把调度逻辑和业务逻辑放在一个项目中,且业务任务信息会持久化到底层数据库表中,对业务系统的侵入性较强;反观xxl-job,调度逻辑和任务信息都注册到调度中心,和业务逻辑及其底层的数据表没有关系;
    • 调度逻辑和业务任务耦合在同一个项目中,这将导致一个问题,在调度任务数量逐渐增多,同时调度任务逻辑逐渐加重的情况下,此时调度系统的性能将大大受限于业务;
    • quartz底层以“抢占式”获取DB锁并由抢占成功节点负责运行任务,会导致节点负载悬殊非常大;而XXL-JOB通过执行器实现“协同分配式”运行任务,充分发挥集群优势,负载各节点均衡。

    当然也有相同点,就是集群模式下,xxl-job和Quartz为了实现一致性,即一个任务调度只会被触发一次,都是采用DB锁的方式实现的。

    相关文章

      网友评论

        本文标题:xxl-job分布式任务调度框架体验

        本文链接:https://www.haomeiwen.com/subject/fdlqhdtx.html