1,传统的定时任务存在哪些缺点?
1,业务逻辑与定时任务逻辑放入同一个jar包中,如果定时任务逻辑挂了也会影响到业务逻辑;
2, 如果服务器集群下,可能存在定时任务会重复触发执行
3,定时惹怒我执行非常消耗cpu的资源,可能会影响到业务线程的执行。
2,定时任务集群,如何保证定时任务幂等性问题。
1,将业务逻辑和定时任务逻辑分开部署,实现解耦,只对业务逻辑实现集群,不对我们的定时任务逻辑集群;一定时任务单机版本,缺点 无法实现高可用的问题;
2,对我们的jar包加上一个开关,项目启动时读取该开关,如果为true的情况下则加载定时任务类,否则情况下不加载定时任务类。 ---缺点: 无法实现高可用的问题。
3, 在数据库加上一个主键能够成功则触发定时任务,否则就不触发定时任务
4,分布式实现,只要jar能够拿到分布式锁就能够执行定时任务,否则不执行。
以上的方案都是属于规模比较小的项目,在微服务架构中应该采用分布式任务调度平台。
传统的定时任务的实现方案: 多线程形式,timetask,线城池,springboot 注解 quartz。
3,分布式任务调度平台设计原理。
xxl-job-admin ---分布式任务调度中心平台
xxl-job-core-----源码实现部分
xxl-job-executor-samples----执行器项目 定时任务模块
定时任务与业务逻辑实现解耦。分开部署,定时任务是个单独的项目
Mayikt-member---会员服务接口
member-job----负责会员服务定时任务
4,XXL-JOB 与ElasticJob 区别
5,分布式任务调度平台如何实现动态启停
6, 分布式任务调度负载均衡策略。
7,分布式任务调度分片集群策略原理
8,如何保证任务调度平台高可用。
分布式任务调度架构设计原理:
xxl-job-admin--分布式任务调度中心平台:
xxl-job-core---源码实现部分
执行器模块: (注册中心)存放实际执行我们定时任务项目模块IP和端口信息
分布式任务调度中心: nginx 负责所有执行器执行定时任务的分配。
原理:
1,执行器启动的时候会将他的ip和端口号注册到执行器上。
2,当我们现在的定时任务模块中启动定时任务的时候,定时任务会在admin项目先触发,会根据执行器的名称查询多个不同的执行的ip信息,在采用负载均衡算法选择一个地址,发送rest请求通知给执行器执行到定时任务。
XXl-job 定时任务框架实现原理。
建议: 定时任务业务逻辑与业务逻辑模块实现分开部署。也就是实现解耦。
会员服务:--会员业务逻辑 不允许有定时任务逻辑。
会员定时任务模块--执行定时任务业务逻辑:
执行器“: 定时业务逻辑模块的项目:
定时任务调度中心(nginx),所有定时任务触发先到达
定时任务调度中心,在驾驶分配到执行器执行。
xxl-job-admin定时任务调度中心模块
执行器模块----定时任务模块----执行器注册中心
原理:
1,当我们的定时任务模块项目启动的时候,会将该ip和端口信息注册到 定时任务注册中心上发送rest请求;
http://127.0.0.1:8080/xxl-job-admin/api/registry
2,需要将定时任务创建在任务调度中心,关联执行器 定时任务模块实际执行ip和端口号
3,创建定时任务会再 xxl-job admin 调度中心 项目先触发,从执行器初测中心查找到执行器接口信息,采用路由策略选择一个执行器(定时任务)地址 发送通知 执行定时任务。配置定时任务规则的时候,建议提前些。
定时任务和业务逻辑代码完全分开,定时任务代码肯定单独的一个项目;
执行器:定时任务业务逻辑;
任务调度平台:
核心:
定时调度模块 所有定时任务需要经过定时调度模块
执行器: 业务逻辑模块
- 执行器定时任务项目,启动时候会将该定时任务接口地址注册到定时任务注册中心中
- 当触发定时任务时候,会先到达任务调度中心,在获取注册中心地址 随机取出一个地址实现rpc远程调用。
- 执行器接收到请求之后,根据handlerid +反射机制执行方法。
缺点:定时任务可能会延迟。
常用时任务调度框架:
Xxl-job、elasticjob、SpringAlibaba Cloud SchedulerX
XXL-JOB任务调度平台
https://www.xuxueli.com/xxl-job/
XXL-job-Admin 平台搭建 任务调度中心
1,官方下载XXL-JobAdmin 的源代码
2,导入xxl-job需要依赖的sql
3,3. 在xxl-job jdb链接配置加上&serverTimezone=UTC 否则报错
4,启动项目
SpringBoot整合XXL-JOB
Maven依赖配置
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.1.2</version>
</dependency>
</dependencies>
Xxl config
@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.");
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();
*/
}
测试任务Demo
@Component
public class MyJobExecutor {
@Value("${xxl.job.executor.port}")
private String executorPort;
@XxlJob("myJobHandler")
public ReturnT<String> myJobHandler(String param) {
System.out.println(">>>myJobHandler触发<<<param:" + param + ",executorPort:" + executorPort);
return ReturnT.SUCCESS;
}
}
网友评论