分布式定时任务 xxl-job 使用

xxl-job简介

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

下载地址

xxl-job 体系结构

见下图,图片摘自官网
在这里插入图片描述调度中心:
其实就是一个单独的web服务(源码中的xxl-job-admin模块),主要是用来设置一些调度任务参数和执行调度任务。
提供了可视化界面,可以更加直观和方便的操作查看调度任务,且调度中心依赖数据库,所有的数据都存储在数据中。
调度中心支持集群模式,但是它们所依赖的数据库必须是同一个,所以同一个集群中的调度中心实例之间是没有任何通信的,数据都是通过数据库共享的
执行器:
执行器是用来执行具体的任务逻辑的,执行器你可以理解为就是平时开发的服务,一个服务实例对应一个执行器实例,每个执行器有自己的名字,为了方便,你可以将执行器的名字设置成服务名
任务:
就是具体调度执行的最小单元,一个执行器中也是可以有多个任务的

总的来说,调用中心是用来控制定时任务的触发逻辑,而执行器是具体执行任务的,这是一种任务和触发逻辑分离的设计思想,这种方式的好处就是使任务更加灵活,可以随时被调用,还可以被不同的调度规则触发。

xxl-job-admin

git上拉下来代码之后结构如下:
xxl-job项目代码首先将文档中的sql文件tables_xxl_job.sql导入到数据当中去,目前只支持MySQL数据库。
然后修改xxl-job-admin模块中的application.properties文件中的数据库连接信息,这个项目本质就是一个spring boot项目,可以根据自己的需求更改。
修改完成之后,可以直接运行该项目也可以打包之后在运行,运行成功之后访问
http://localhost:8080/xxl-job-admin
,如果在配置文件修改了配置则根据修改的访问url。默认的用户名是admin,密码是123456
到此xxl-job调度中心部署完毕。

Spring Boot整合xxl-job

导入依赖

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

修改配置文件,增加xxl-job配置

xxl:
  job:
    accessToken: default_token #根据xxl-job-admin中设置的配置这里
    admin:
      addresses: http://127.0.0.1:8080/xxl-job-admin
    executor:
      appname: xbx-dev # 这里需要再xxl-admin中的执行器名称,如果没有需要现在xxl-job-admin中添加。
      ip: 127.0.0.1
      port: 9999

编写配置类

@Configuration
public class XxlJobConfiguration {

    private final Logger logger = LoggerFactory.getLogger(XxlJobConfiguration.class);

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

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

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

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

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

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init. <<<<<<<<<<<");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        return xxlJobSpringExecutor;
    }

}

到此Spring Boot导入xxl-job完成,运行项目提示xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999则运行成功。

BEAN模式

业务代码

@XxlJob("test")
public void test(){
    LocalDateTime now = LocalDateTime.now();
    System.out.println(now + " 简单任务执行了。。。。");
}

调度中心增加任务
调度中心设置设置完成后开启任务,并且启动代码程序。查看控制台信息,这是就会根据设置的时间定时执行所设置的任务方法。

GLUE模式

根据上边介绍,克制如果想要一个方法让xxl-job调度,就必须要@XxlJob注解修饰方法,但是,有时会有需求在不改代码的基础上,让某个方法完成xxl-job调度。这是BEAN模式就不在适应,接着导入这一小节主题GLUE模式。
运行模式选择
GLUE模式分为多种语言类型,这里仅使用java语言类型。
编写业务方法

@Service
public class GLUETestJobHandler {
    private final Logger logger = LoggerFactory.getLogger(GLUETestJobHandler.class);

    public void testGlue(){
        LocalDateTime now = LocalDateTime.now();
        logger.info("测试xxl-job GLUE模式 time => {}", now);
    }

}

xxl-job调度中心任务配置中任务模式选择“GLUE(java)”模式,其余的设置和BEAN模式中的相同。设置完了之后选择任务的 GLUE IDE。
在这里插入图片描述
进入到IDE中去,这里代码是通过继承IJobHandler模版,并重写模版方法,从而实现我们需要的功能。GULE IDE

路由策略

上边设置任务时路由策略都是默认的,就是第一个,但是当微服务集群的时候,只是第一个就不行了,需要把任务执行分配到集群的各个服务上,这就需要另一个路由策略,分片广播策略。
分片广播策略
集群分片的模式主要有两种,取模分片和范围分片。
这里通过一个案例来解释集群分片策略。如:当前有一个需求需要定时的给一些用户发送短信信息。
正常的思路是,查询出需要发送消息的用户,根据查询出的信息给用户推送消息,但是如何设置路由策略为第一个或i这轮询等等,都是一次任务调度都指定到一个微服务上,这样集群就毫无作用了。所以采用集群分片路由策略
业务代码:

@Data
public class UserMobilePlan {

    private Long id;
    private String username;

    private String nickname;

    private String phone;

    private String info;
}
/** 
 * 调度任务
 **/
@Component
public class TestJobHandler {
    private final Logger logger = LoggerFactory.getLogger(TestJobHandler.class);

    @Autowired
    private UserMobilePlanMapper userMobilePlanMapper;

    @XxlJob("sendMsgHandler")
    public void sendMsgHandler() throws InterruptedException {
		//当前分片数
        int shardIndex = XxlJobHelper.getShardIndex();
        //分片总数
        int shardTotal = XxlJobHelper.getShardTotal();
        System.out.println("shardIndex:"+shardIndex+";shardTotal:"+shardTotal);
        List<UserMobilePlan> userMobilePlans = new ArrayList<>();
        //取模分片 查询数据
        if (shardTotal == 1){
            userMobilePlans= userMobilePlanMapper.selectAll();
        }else {
            userMobilePlans = userMobilePlanMapper.selectByMod(shardIndex,shardTotal);
        }


        System.out.println("任务开始时间:"+LocalDateTime.now()+",处理任务的数量:"+userMobilePlans.size());
        long startTime = System.currentTimeMillis();
        userMobilePlans.forEach(userMobilePlan -> {
            try {
                //模拟短信发送
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });

        System.out.println("任务结束时间:"+LocalDateTime.now());
        System.out.println("任务耗时:"+(System.currentTimeMillis() - startTime)+"毫秒");

    }
  
}
@Mapper
public interface UserMobilePlanMapper {
	/** 
	 * 根据id和分片总数取模的值等于分片数查询出当前服务需要处理的数据,这样集群中的所有服务就不会执行冲突
	 **/
    @Select("select * from user_mobile_plan where mod(id,#{shardingTotal} = #{shardingIndex})")
    List<UserMobilePlan> selectByMod(@Param("shardingIndex") Integer shardingIndex,@Param("shardingTotal") Integer shardingTotal);

}

运行服务可以看到结果
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值