preface
Text has been included to my lot warehouse, welcome Star:https://github.com/bin392328206/six-finger plant a tree is the best time ten years ago, the second is writing a blog on the way now encourage everyone in technology
omg
Because I used xxL-job a lot before, and then I changed its edge business code into the appropriate usage of my company, such as our dynamic timing task, call interface, etc., but I haven’t had a chance to comb through its core source code, so I will try to comb through it together sometime. But I would like to say that this article is the interpretation of the principle, not suitable for xxL-job beginners, I default you have at least a certain understanding of XXL-job, if you want to go to the entry, first go to the following official documents
- xxl-job
Architecture diagram
The diagram above shows the overall architecture of version 2.1 for our source code analysis. It is divided into two blocks, scheduling center and executor. Let’s analyze the code of the scheduling center, namely xxl-job-admin package.
Main process
Xxl-job is based on SpringBoot, so our first step is of course to start the Spring application XxlJobAdminApplication, It then has a configuration class XxlJobAdminConfig that implements the InitializingBean, which Spring loads after initialization, as shown below
Then we’ll look at xxlJobscheduler.init (); Method, as shown below
- The first step is internationalization.
- The second step is monitoring related.
- The third step is related to failure retry.
- The fourth step is to start the admin service and receive registration requests.
- 5. The JobScheduleHelper scheduler, in an indeterminate loop, obtains the task in the xxl_job_info table, updates the next execution time, and calls JobTriggerPoolHelper to send the task to the scheduler
There are a lot of things we need to know about the above steps, but today we are going to pick some of them and go straight to the last step, JobScheduleHelper
JobScheduleHelper
A very important class, let’s look at its start() method
In fact, it is very simple to start 2 background threads, these 2 threads are infinite loop, but these 2 threads are also very important. Let’s look at them one by one
I just copied the code, and we’ll talk about it
- The code in the loop is shown above, first using the for UPDATE statement to obtain the qualification lock for the task, and then to obtain the task to be executed in the next 5 seconds.
Actually this kind of code is our business. If you don’t come with your eyes closed, haha returns a List of JobInfo. What if we were writing the code? The first one is of course to determine whether it is empty, and then traverse to process each object, not to mention xxL-job is also like this, and then do different business logic processing according to the different attributes of the object, haha, do you think the open source framework and our usual code is similar.
TriggerNextTime (triggerNextTime); triggerNextTime (triggerNextTime); triggerNextTime (triggerNextTime
- The trigger time of the current task of the first branch has exceeded 5 seconds, so the next trigger time is directly calculated.
- If the trigger time of the second branch is satisfied, the class JobTriggerPoolHelper is used for task scheduling. Then, if the next execution time is determined to be within 5 seconds, the data of this task is cached, and the processing logic is the same as that of the third branch.
- PushTimeRing (ringSecond, jobinfo.getid ());
private void pushTimeRing(int ringSecond, int jobId){
// push async ring
List<Integer> ringItemData = ringData.get(ringSecond);
if (ringItemData == null) {
ringItemData = new ArrayList<Integer>();
ringData.put(ringSecond, ringItemData); } ringItemData.add(jobId); logger.debug(">>>>>>>>>>> xxl-job, schedule push time-ring : " + ringSecond + "=" + Arrays.asList(ringItemData) ); } Copy the code
RingData is a Map set whose key is an integer ranging from 0 to 59 and whose value is a jobId set. The processing logic for this set of data resides in our second daemon thread, ringThread.
- Let’s take a look at our second daemon thread
// ring thread
ringThread = new Thread(new Runnable() {
@Override
public void run() {
// align second try { TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis()%1000 ); } catch (InterruptedException e) { if(! ringThreadToStop) { logger.error(e.getMessage(), e); } } while(! ringThreadToStop) { try { // second data List<Integer> ringItemData = new ArrayList<>(); int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // To avoid too long processing time, step over the scale, check a scale forward; 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.size() > 0) { // do trigger for (int jobId: ringItemData) { // do trigger JobTriggerPoolHelper.trigger(jobId, TriggerTypeEnum.CRON, -1, null, 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); } } } logger.info(">>>>>>>>>>> xxl-job, JobScheduleHelper#ringThread stop"); } }); ringThread.setDaemon(true); ringThread.setName("xxl-job, admin JobScheduleHelper#ringThread"); ringThread.start(); Copy the code
The task of the time wheel is obtained based on the current seconds scale and the previous scale, and then the task is scheduled using JobTriggerPoolHelper as above.
Sequence diagram
Daily for praise
All right, everybody, that’s all for this article. All the people here are talented.
Creation is not easy, your support and recognition, is the biggest motivation for my creation, we will see in the next article
Six pulse excalibur | article “original” if there are any errors in this blog, please give criticisms, be obliged!
This article is formatted using MDNICE