任务调度中心xxl-job的搭建使用

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.背景

项目场景中,往往许多场景中需要分布式任务调度,而目前基于springcloud的项目中,因业务需求逐步的完善的,许多模块中也添加了自己的定时任务,除了代码维护性低,也存在以下问题: (1)同一服务多个实例的任务存在互斥时,需要统一协调 (2)定时任务的执行需要支持高可用、监控运维、故障告警 (3)需要统一管理和追踪各个服务节点定时任务的运行情况,以及任务属性信息,例如任务所属服务、所属责任人

2.技术选型

调研了目前比较流行的几个任务调度框架,具体比较如下(图摘自网络): 在这里插入图片描述 xxl-job 1、源码下载地址   ①、GitHub:github.com/xuxueli/xxl… ②、码云:gitee.com/xuxueli0323…

2、文档地址   ①、中文文档:www.xuxueli.com/xxl-job/#/

  ②、英文文档:www.xuxueli.com/xxl-job/en/…

从比较中可以看出,xxl-job开发迅速、学习简单、轻量级、易扩展、开箱即用,具有以下特性:

简单灵活 提供Web页面对任务进行管理,管理系统支持用户管理、权限控制; 支持容器部署; 支持通过通用HTTP提供跨平台任务调度;

丰富的任务管理功能 支持页面对任务CRUD操作; 支持在页面编写脚本任务、命令行任务、Java代码任务并执行; 支持任务级联编排,父任务执行结束后触发子任务执行; 支持设置任务优先级; 支持设置指定任务执行节点路由策略,包括轮询、随机、广播、故障转移、忙碌转移等; 支持Cron方式、任务依赖、调度中心API接口方式触发任务执行 高性能 调度中心基于线程池多线程触发调度任务,快任务、慢任务基于线程池隔离调度,提供系统性能和稳定性; 任务调度流程全异步化设计实现,如异步调度、异步运行、异步回调等,有效对密集调度进行流量削峰; 高可用 任务调度中心、任务执行节点均 集群部署,支持动态扩展、故障转移 支持任务配置路由故障转移策略,执行器节点不可用是自动转移到其他节点执行 支持任务超时控制、失败重试配置 支持任务处理阻塞策略:调度当任务执行节点忙碌时来不及执行任务的处理策略,包括:串行、抛弃、覆盖策略 易于监控运维 支持设置任务失败邮件告警,预留接口支持短信、钉钉告警; 支持实时查看任务执行运行数据统计图表、任务进度监控数据、任务完整执行日志;

3.架构图

在这里插入图片描述

调度模块(调度中心): 负责管理调度信息,按照调度配置发出调度请求,自身不承担业务代码。调度系统与任务解耦,提高了系统可用性和稳定性,同时调度系统性能不再受限于任务模块; 支持可视化、简单且动态的管理调度信息,包括任务新建,更新,删除,任务报警等,所有上述操作都会实时生效,同时支持监控调度结果以及执行日志,支持执行器Failover

执行模块(执行器): 负责接收调度请求并执行任务逻辑。任务模块专注于任务的执行等操作,开发和维护更加简单和高效; 接收“调度中心”的执行请求、终止请求和日志请求等

4.工作原理

在这里插入图片描述

任务执行器根据配置的调度中心的地址,自动注册到调度中心

达到任务触发条件,调度中心下发任务 执行器基于线程池执行任务,并把执行结果放入内存队列中、把执行日志写入日志文件中 执行器的回调线程消费内存队列中的执行结果,主动上报给调度中心 当用户在调度中心查看任务日志,调度中心请求任务执行器,任务执行器读取任务日志文件并返回日志详情

5.搭建使用

1.首先下载源代码,导入项目模块中 在这里插入图片描述 2.配置文件 因为需要将这份代码,转变成springcloud中独立服务使用,所以需要根据项目的习惯做一样的修改,以下是针对xxl-job-admin模块的说明: 数据库初始化脚本执行后,bootstrap.yml配置必须的配置,如数据库,消息中间件等,application.yml如下

server:
  port: 9997
  #actuator
  servlet:
    context-path: /xxl-job-admin
management:
  server:
    servlet:
      context-path: /actuator
  health:
    mail:
      enabled: false

### mybatis
mybatis:
  mapper-locations: /mybatis-mapper/*Mapper.xml
spring:
  mvc:
    static-path-pattern: /static/**
    servlet:
      load-on-startup: 0
    resources:
      static-locations: classpath:/static/

### freemarker
  freemarker:
    templateLoaderPath: classpath:/templates/
    suffix: .ftl
    charset: UTF-8
    request-context-attribute: request
    settings.number_format: 0.##########

### xxl-job, datasource
  datasource:
    url: jdbc:mysql://${db_ip_port}/xxx?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: ${db_username}
    password: ${db_password}
    driver-class-name: com.mysql.cj.jdbc.Driver

#这个段配置是源码的,改成了项目使用的配置中心druid
### datasource-pool
#    type: com.zaxxer.hikari.HikariDataSource
#    hikari:
#      minimum-idle: 10
#      maximum-pool-size: 30
#      auto-commit: true
#      idle-timeout: 30000
#      pool-name: HikariCP
#      max-lifetime: 900000
#      connection-timeout: 10000
#      connection-test-query: SELECT 1

### xxl-job, email
  mail:
    host: smtp.qq.com
    port: 25
    username: [email protected]
    password: xxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory
### xxl-job, access token
xxl:
  job:
    accessToken:
### xxl-job, i18n (default empty as chinese, "en" as english)
    i18n:
## xxl-job, triggerpool max size
    triggerpool:
      fast:
        max: 200
      slow:
        max: 100
### xxl-job, log retention days
    logretentiondays: 30

3.启动项目 访问地址:http://localhost:9997/xxl-job-admin/toLogin 默认账号密码admin 123456 在这里插入图片描述在这里插入图片描述 4.客户端对接 <1>maven依赖

<dependency>
			<groupId>com.xuxueli</groupId>
			<artifactId>xxl-job-core</artifactId>
			<version>${project.parent.version}</version><!--版本自行编写-->
		</dependency>

<2>增加配置信息 其中appname和界面创建的执行器名称要一致,这里取的是服务名称

### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl:
  job:
    admin:
      addresses: http://localhost:9997/xxl-job-admin
    executor:
      appname: ${spring.application.name}
      ip:
      port: 9999
      logpath: /usr/local/logs/${spring.application.name}/scheduling
      logretentiondays: 30
    accessToken:

<3>增加spring扫描路径 源码中需要在对接的客户端增加初始化配置类,由于每个客户端需要依赖xxl-job-core,所以将配置类放入该依赖模块中,客户端启动类配置扫描路径即可@SpringBootApplication(scanBasePackages = {"xx.xxx.xxxxx.configuration"})

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

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

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

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

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

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

    @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.");
        logger.info(">>>>>>>>>>> 定时任务配置初始化");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppName(appName);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    }

    /**
     * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
     *
     *      1、引入依赖:
     *          <dependency>
     *             <groupId>org.springframework.cloud</groupId>
     *             <artifactId>spring-cloud-commons</artifactId>
     *             <version>${version}</version>
     *         </dependency>
     *
     *      2、配置文件,或者容器启动变量
     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
     *
     *      3、获取IP
     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
     */
}

<4>编写需要定时执行的业务代码 (1)类的形式 开发一个继承自"com.xxl.job.core.handler.IJobHandler"的JobHandler类,实现其中任务方法。

 @JobHandler(value = "cs1DbJobHandler")
@Component
public class Cs1DbJobHandler extends IJobHandler {
 
    @Autowired
    ICs1DbService cs1DbService;
 
    @Override
    public ReturnT<String> execute(String s){
        XxlJobLogger.log("hello world.");
        return ReturnT.SUCCESS;
    }
}

(2)方法的形式 1、在Spring Bean实例中,开发Job方法,方式格式要求为 "public ReturnT execute(String param)" 2、为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。 3、执行日志:需要通过 "XxlJobLogger.log" 打印执行日志;

@Component
public class TestSchedualing {

    @XxlJob("myFirstDemo")
    public ReturnT<String> execute(String param) {
        XxlJobLogger.log("hello world.");
        return ReturnT.SUCCESS;
    }
}

<5>登录平台创建执行器 在这里插入图片描述 <6>创建任务 任务中JobHandler就是我们代码中@XxlJob注解的值,这样平台才能找到对应的代码执行, 常用路由策略: 第一个:总在第一个注册的服务上执行 轮询(推荐):每个服务依次执行(每次只有一个) 随机:随机一个节点执行 在这里插入图片描述 对cron表达式的补充说明: cron表达式右边按钮可以自动生成表达式,假如需要生成每小时的定时任务, 1.第一步需要选择小时中每小时执行一次。 在这里插入图片描述 2.除了指定每小时的轮询外,需要指定具体的时候进行执行,所以需要在分和秒中选择具体的时间,若不选择,将会每秒执行。当然,也可以选择除了整点以外的时间。注意:如果需要不同的时间点执行,则需要创建多个定时任务,例如每天早上8.30和9.45执行,这样需要分别创建各自的任务。 在这里插入图片描述 在这里插入图片描述 若有动态创建定时任务的需求,这时候就需要使用接口的形式进行创建,源码也是提供了任务的增删改查的接口,源码路径为 com.xxl.job.admin.controller.JobInfoController com.xxl.job.admin.controller.JobGroupController 大家可以按需增加接口,例如批量的接口。

猜你喜欢

转载自juejin.im/post/7114468657161306125
今日推荐