分布式任务调度平台XXL-JOB

Posted 一个搬砖的农民工

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式任务调度平台XXL-JOB相关的知识,希望对你有一定的参考价值。

支持原文:https://www.cnblogs.com/chen-chen-chen/p/12221923.html
官网地址:https://www.xuxueli.com/xxl-job/

发展史

  • 第一阶段 单线程调度,在Java1.5之前,基于线程的等待(sleep或wait)机制定时执行,需要开发者实现调度逻辑,单个线程(Thread)处理单个任务有些浪费,但是一个线程(Timer)处理多个任务容易因为某个任务繁忙导致其他任务阻塞。
  • 第二阶段 线程池调度,在Java1.5开始提供ScheduledExecutorService调度线程池,调度线程池支持固定的延时和固定间隔模式,对于需要在某天或者某月的时间点执行就不大方便,需要计算时间间隔,转换成启动延时和固定间隔,处理起来比较麻烦。
  • 第三阶段 Spring任务调度,Spring简化了任务调度,通过@Scheduled注解支持将某个Bean的方法定时执行,除了支持固定延时和固定间隔模式外,还支持cron表达式,使得定时任务的开发变得极其简单。
  • 第四阶段 Quartz任务调度,在任务服务集群部署下,Quartz通过数据库锁,实现任务的调度并发控制,避免同一个任务同时执行的情况。Quartz通过Scheduler提供了任务调度API,开发可以基于此开发自己的任务调度管理平台。
  • 第五阶段 分布式任务平台,提供一个统一的平台,无需再去做和调度相关的开发,业务系统只需要实现具体的任务逻辑,自动注册到任务调度平台,在上面进行相关的配置就完成了定时任务的开发。

解决方案

现在分布式下任务调度有很多解决方案,可以基于Quartz开发任务管理平台,也可以使用开源的任务调度平台,比如xxl-job,elastic-job。

XXL-JOB
大众点评员工徐雪里于2015年发布的分布式任务调度平台,是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。官方地址:https://www.xuxueli.com/xxl-job/

ELASTIC-JOB
当当开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分布式协调,实现任务高可用以及分片,并且可以支持云开发,由两个相互独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成。官方地址:http://elasticjob.io/docs/elastic-job-lite/00-overview/

方案对比

使用XXL-JOB

XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。

如何在项目中集成
1.加入依赖

<dependency>
  <groupId>com.xuxueli</groupId>
  <artifactId>xxl-job-core</artifactId>
  <version>2.0.1</version>
</dependency>

2.配置执行器

@Configuration
public class XxlJobConfig 
    @Value("$spring.application.name:")
    private String springAppName;

    @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:9999")
    private int port;

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

    @Value("$xxl.job.executor.logpath:job-logs")
    private String logPath;

    @Value("$xxl.job.executor.logretentiondays:7")
    private int logRetentionDays;

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() 
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        if (StringUtils.isEmpty(appName)) 
            if (StringUtils.isEmpty(springAppName)) 
                throw new IllegalStateException("missing xxl-job appname config");
            
            appName = springAppName;
        
        xxlJobSpringExecutor.setAppName(appName);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);

        return xxlJobSpringExecutor;
    

3.配置yml文件

server:
  #项目端口号
  port: 8081
logging:
  #日志文件
  config: classpath:logback.xml

xxl:
  job:
    admin:
      #调度中心部署跟地址:如调度中心集群部署存在多个地址则用逗号分隔。
      #执行器将会使用该地址进行"执行器心跳注册""任务结果回调"。
      addresses: http://127.0.0.1:8080/xxl-job-admin

    #分别配置执行器的名称、ip地址、端口号
    #注意:如果配置多个执行器时,防止端口冲突
    executor:
      appname: executorDemo
      ip: 127.0.0.1
      port: 9999

      #执行器运行日志文件存储的磁盘位置,需要对该路径拥有读写权限
      logpath: /data/applogs/xxl-job/jobhandler
      #执行器Log文件定期清理功能,指定日志保存天数,日志文件过期自动删除。限制至少保持3天,否则功能不生效;
      #-1表示永不删除
      logretentiondays: -1

addresses:任务调度中心部署根地址(必填)
appname:这个名称可以自己定义,但一般为 “项目名称-job” ,此名称用于在任务调度中心中,配置执行器时的名称标识。
ip:执行器ip,可以不填,会自动识别注册
port:执行器端口号
logpath:执行器运行日志文件存储磁盘路径
logretentiondays:执行器日志保存天数,值大于3时生效,启用执行器log文件定期清理功能,否则不生效。
AccessToken:执行器通讯token,非空时启用

4.开发定时任务
定义定时任务有两种方式:1、2.1.2或者之后版本可以直接在方法上加@XxlJob来声明任务;2、2.1.2之前版本每个任务需要单独开发一个Bean,实现IJobHandler接口,并且在类上加@JobHandler注解。第二种方式较麻烦,推荐使用第一种方式(目前还没稳定版)。

基于@XxlJob注解代码方式(建议制定名称,和调度中心配置保持一致)

@Component
public class SampleXxlJob 
    private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class);

    /**
     * 1、简单任务示例(Bean模式)
     */
    @XxlJob("demoJobHandler")
    public ReturnT<String> demoJobHandler(String param) throws Exception 
        XxlJobLogger.log("XXL-JOB, Hello World.");
        for (int i = 0; i < 5; i++) 
            XxlJobLogger.log("beat at:" + i);
            TimeUnit.SECONDS.sleep(2);
        
        return ReturnT.SUCCESS;
    

    /**
     * 2、分片广播任务
     */
    @XxlJob("shardingJobHandler")
    public ReturnT<String> shardingJobHandler(String param) throws Exception 
        // 分片参数
        ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
        XxlJobLogger.log("分片参数:当前分片序号 = , 总分片数 = ", shardingVO.getIndex(), shardingVO.getTotal());
        // 业务逻辑
        for (int i = 0; i < shardingVO.getTotal(); i++) 
            if (i == shardingVO.getIndex()) 
                XxlJobLogger.log("第  片, 命中分片开始处理", i);
             else 
                XxlJobLogger.log("第  片, 忽略", i);
            
        
        return ReturnT.SUCCESS;
    

基于@JobHandler代码方式

@JobHandler(value="demoJobHandler")
@Component
public class DemoJobHandler extends IJobHandler 
	@Override
	public ReturnT<String> execute(String param) throws Exception 
		XxlJobLogger.log("XXL-JOB, Hello World.");
		for (int i = 0; i < 5; i++) 
			XxlJobLogger.log("beat at:" + i);
			TimeUnit.SECONDS.sleep(2);
		
		return SUCCESS;
	

5.配置定时任务
1、配置定时任务,需要先配置执行器,推荐使用自动注册方式,避免集群部署时还需要调整机器地址,添加界面如下(注意appname要和业务系统中配置一致):
2、添加完执行器后,添加任务,JobHandler要和代码中配置的名称一致,执行器集群部署可以通过配置路由方式来控制执行,xxl-job调度只支持cron表达式。

3、启动或者执行任务,查询执行日志、注册节点等

集成踩坑记录

1、任务服务器必须做时钟同步,执行器时钟不能调度中心180秒,否则将会导致调度失败(RPC框架限制)
2、调度任务的时间间隔低于实际执行耗时,导致产生较大的调度日志;
3、尽量避免短任务,比如秒级的任务会导致大量数据库锁影响性能;
4、调度日志量偏大导致查询慢,由于日志都记录在数据库,需要定时清理;
5、自动注册时服务器多网卡导致调度失败,注册时需指定网卡IP;

以上是关于分布式任务调度平台XXL-JOB的主要内容,如果未能解决你的问题,请参考以下文章

三分钟搞定 XXL-JOB 分布式任务调度平台

xxl-job分布式任务调度平台

任务调度平台XXL-JOB使用

分布式任务调度平台XXL-JOB学习

分布式任务调度平台XXL-JOB搭建

《分布式任务调度平台XXL-JOB》