分布式调度平台XXL-JOB源码分析-调度中心
架构图
上图是我们要进行源码分析的2.1版本的整体架构图。其分为两大块,调度中心和执行器,本文先分析调度中心,也就是xxl-job-admin这个包的代码。
关键bean
在application.properties配置正确的数据库连接信息后,直接启动XxlJobAdminApplication即可。
配置类XxlJobAdminConfig,里面维护了一些调度中心端的配置数据。
XxlJobScheduler这个组件实现了InitializingBean接口,所以spring容器在初始化的时候会调用afterPropertiesSet方法,此方法如下:
第一步国际化相关。
第二步监控相关。
第三步失败重试相关。
第四步启动admin端服务,接收注册请求等。
第五步JobScheduleHelper调度器,死循环,在xxl_job_info表里取将要执行的任务,更新下次执行时间的,调用JobTriggerPoolHelper类,来给执行器发送调度任务的
JobScheduleHelper
这个类就是死循环从xxl_job_info表中取出未来5秒内要执行的任务,进行调度分发。
启动了两个守护线程,先来看scheduleThread。
死循环内的代码如上图,首先利用for update语句进行获取任务的资格锁定,再去获取未来5秒内即将要执行的任务。
展开遍历任务的逻辑代码,有三个分支
第一个分支当前任务的触发时间已经超时5秒以上了,不在执行,直接计算下一次触发时间。
第二个分支为触发时间已满足,利用JobTriggerPoolHelper这个类进行任务调度,之后判断下一次执行时间如果在5秒内,进行此任务数据的缓存,处理逻辑与第三个分支一样。
对触发时间秒数进行60取模,跟进pushTimeRing方法
ringData是以0到59的整数为key,以jobId集合为value的Map集合。这个集合数据的处理逻辑,就在我们第二个守护线程ringThread中。
while (!ringThreadToStop) {
try {
// second data
List<Integer> ringItemData = new ArrayList<>();
int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度;
for (int i = 0; i < 2; i++) {
List<Integer> tmpData = ringData.remove( (nowSecond+60-i)%60 );
if (tmpData != null) {
ringItemData.addAll(tmpData);
}
}
// ring trigger
logger.debug(">>>>>>>>>>> xxl-job, time-ring beat : " + nowSecond + " = " + Arrays.asList(ringItemData) );
if (ringItemData!=null && ringItemData.size()>0) {
// do trigger
for (int jobId: ringItemData) {
// do trigger
JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, null);
}
// clear
ringItemData.clear();
}
} catch (Exception e) {
if (!ringThreadToStop) {
logger.error(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread error:{}", e);
}
}
// next second, align second
try {
TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis()%1000);
} catch (InterruptedException e) {
if (!ringThreadToStop) {
logger.error(e.getMessage(), e);
}
}
}
根据当前秒数刻度和前一个刻度进行时间轮的任务获取,之后和上文一样,利用JobTriggerPoolHelper进行任务调度。
时序图
JobTriggerPoolHelper
如前文所述,不管是scheduleThread还是ringThread,最后完成任务调度的都是JobTriggerPoolHelper.trigger方法,这个类有两个线程池fastTriggerPool和slowTriggerPool,顾名思义,分别是执行较快任务和较慢任务的,后查官方文档,如下:
minTim属性,作用待明确
jobTimeoutCountMap属性,计数,key为jobId,value使用AtomicInteger计数。
helper静态变量指向自己本身,提供外部静态方法调用。
重要方法,向两种线程池其中之一提交调度任务,进行调度,引出XxlJobTrigger这个类,一路跟进去
继续跟进
至此,完成执行器的任务调度。
时序图
接收注册和心跳请求
分布式调度平台XXL-JOB源码分析-调度中心的更多相关文章
- quartz集群调度机制调研及源码分析---转载
quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...
- 定时组件quartz系列<三>quartz调度机制调研及源码分析
quartz2.2.1集群调度机制调研及源码分析引言quartz集群架构调度器实例化调度过程触发器的获取触发trigger:Job执行过程:总结:附: 引言 quratz是目前最为成熟,使用最广泛的j ...
- (1)quartz集群调度机制调研及源码分析---转载
quartz2.2.1集群调度机制调研及源码分析 原文地址:http://demo.netfoucs.com/gklifg/article/details/27090179 引言quartz集群架构调 ...
- 鸿蒙内核源码分析(调度故事篇) | 用故事说内核调度 | 百篇博客分析OpenHarmony源码 | v9.07
百篇博客系列篇.本篇为: v09.xx 鸿蒙内核源码分析(调度故事篇) | 用故事说内核调度过程 | 51.c.h .o 前因后果相关篇为: v08.xx 鸿蒙内核源码分析(总目录) | 百万汉字注解 ...
- 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07
百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...
- 深入理解分布式调度框架TBSchedule及源码分析
简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...
- scheduler源码分析——调度流程
前言 当api-server处理完一个pod的创建请求后,此时可以通过kubectl把pod get出来,但是pod的状态是Pending.在这个Pod能运行在节点上之前,它还需要经过schedule ...
- 基于Linux平台的libpcap源码分析和优化
目录 1..... libpcap简介... 1 2..... libpcap捕包过程... 2 2.1 数据包基本捕包流程... 2 2.2 libpcap捕包过程... ...
- Cocos2d-X3.0 刨根问底(六)----- 调度器Scheduler类源码分析
上一章,我们分析Node类的源码,在Node类里面耦合了一个 Scheduler 类的对象,这章我们就来剖析Cocos2d-x的调度器 Scheduler 类的源码,从源码中去了解它的实现与应用方法. ...
随机推荐
- php_MVC实现步骤二
2.match_split 显示逻辑相分离 将功能强制分成两个部分,显示html文件,和逻辑PHP文件: 要求浏览器请求负责功能的PHP逻辑文件: 该PHP逻辑文件,对需要的显示内容进行载入. 逻辑P ...
- LeetCode 1051. 高度检查器(Height Checker) 28
1051. 高度检查器 1051. Height Checker 题目描述 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列. 请你返回至少有多少个学生没有站在正确位置数量.该人数指的是 ...
- 【面试】C++类中的相关函数【构造,拷贝构造,析构,友元】
构造函数:值的初始化,可带参数,无返回值,可重载,可存在多个 析构函数:释放对象内存空间,无参数,无返回值,不可重载,只能存在一个 拷贝构造函数:拷贝对象,其形参必须是引用 1.空类会默认添加哪些东西 ...
- 手写简化版SpringBoot
Springboot项目全部依赖注解的,web工程是如何启动的 1 首先引入了Tomcat依赖,然后用java代码启动Tomcat容器,默认Tomcat版本是8.5版本 2 Tomcat是实现了ser ...
- 采用socket传输文件
采用socket传输文件 客户端输入文件的地址,服务端判断文件存在,就将文件传输到客户端 package com.fly.socket; import java.io.BufferedInputStr ...
- Apache Kafka教程
1.卡夫卡教程 今天,我们正在使用Apache Kafka Tutorial开始我们的新旅程.在这个Kafka教程中,我们将看到什么是Kafka,Apache Kafka历史以及Kafka的原因.此外 ...
- Java开发笔记(一百三十一)Swing的列表框
前面介绍了选择框的用法,当时为了方便用户勾勾点点,无论是复选框还是单选按钮,统统把所有选项都摆在界面上.倘若只有两三个选项还好办,要是选项数量变多比如超过五个,这么多的选择框一齐在界面罗列,不光程序员 ...
- hdu 2962 题解
题目 题意 给出一张图,每条道路有限高,给出车子的起点,终点,最高高度,问在保证高度尽可能高的情况下的最短路,如果不存在输出 $ cannot reach destination $ 跟前面 $ ...
- 关于base64的一个小细节
Base64出现\r\n的问题 前段时间遇到这么一个小问题: 后台接口返回一个图片的base64串,同事拿着这个字符串,找了一个在线图片和Base64字符串互转的工具网站,想将字符串转成图片,死活转不 ...
- Socket HttpListen
HttpListener sSocket = new HttpListener(); sSocket.Prefixes.Add("http://127.0.0.1:8080/"); ...