自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

揭秘XXLJOB:任務(wù)調(diào)度和執(zhí)行的全面指南

開發(fā) 前端
在本期文章中,向大家介紹了XXLJOB是如何啟動和執(zhí)行任務(wù)的,在下期文章中將向大家介紹XXLJOB其他的細(xì)節(jié),由于一個定時任務(wù)系統(tǒng)的復(fù)雜,很多內(nèi)容還是需要各位讀者自己看一遍才能真正的理解,畢竟代碼才是真正的老師。

本文主要向大家介紹一下xxljob在調(diào)度任務(wù)時執(zhí)行了哪些操作,這也是xxljob最核心的功能

表結(jié)構(gòu)

xxljob是如何觸發(fā)任務(wù)的,首先我們先了解一下xxljob的表結(jié)構(gòu)

xxl_job_info 記錄的是各個具體job的信息 是xxljob中最重要的表 這張表記錄的job 的調(diào)度類型,調(diào)度時機(jī),路由策略,阻塞策略等信息

CREATE TABLE `xxl_job_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `job_group` int(11) NOT NULL COMMENT '執(zhí)行器主鍵ID',
  `job_desc` varchar(255) NOT NULL,
  `add_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `author` varchar(64) DEFAULT NULL COMMENT '作者',
  `alarm_email` varchar(255) DEFAULT NULL COMMENT '報警郵件',
  `schedule_type` varchar(50) NOT NULL DEFAULT 'NONE' COMMENT '調(diào)度類型',
  `schedule_conf` varchar(128) DEFAULT NULL COMMENT '調(diào)度配置,值含義取決于調(diào)度類型',
  `misfire_strategy` varchar(50) NOT NULL DEFAULT 'DO_NOTHING' COMMENT '調(diào)度過期策略',
  `executor_route_strategy` varchar(50) DEFAULT NULL COMMENT '執(zhí)行器路由策略',
  `executor_handler` varchar(255) DEFAULT NULL COMMENT '執(zhí)行器任務(wù)handler',
  `executor_param` varchar(512) DEFAULT NULL COMMENT '執(zhí)行器任務(wù)參數(shù)',
  `executor_block_strategy` varchar(50) DEFAULT NULL COMMENT '阻塞處理策略',
  `executor_timeout` int(11) NOT NULL DEFAULT '0' COMMENT '任務(wù)執(zhí)行超時時間,單位秒',
  `executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失敗重試次數(shù)',
  `glue_type` varchar(50) NOT NULL COMMENT 'GLUE類型',
  `glue_source` mediumtext COMMENT 'GLUE源代碼',
  `glue_remark` varchar(128) DEFAULT NULL COMMENT 'GLUE備注',
  `glue_updatetime` datetime DEFAULT NULL COMMENT 'GLUE更新時間',
  `child_jobid` varchar(255) DEFAULT NULL COMMENT '子任務(wù)ID,多個逗號分隔',
  `trigger_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '調(diào)度狀態(tài):0-停止,1-運(yùn)行',
  `trigger_last_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '上次調(diào)度時間',
  `trigger_next_time` bigint(13) NOT NULL DEFAULT '0' COMMENT '下次調(diào)度時間',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

xxl_job_log 這張表記錄了job執(zhí)行時的一些參數(shù) 包括了執(zhí)行次數(shù) 執(zhí)行參數(shù) jobid, 調(diào)度的時機(jī)和結(jié)果 xxl_job_log_report 記錄了調(diào)度中心的統(tǒng)計(jì)數(shù)據(jù) xxl_job_logglue記錄了glue類型job的日志

xxl_job_registry 記錄了在調(diào)度中心注冊的執(zhí)行器信息 xxl_job_group 記錄了調(diào)度中心的分組情況 xxl_job_user 記錄了用戶信息 xxl_job_lock記錄了鎖信息 其實(shí)我們通過表的設(shè)計(jì)就以了解一些xxljob的設(shè)計(jì)思想,下面我們就來看一下一個任務(wù)是如何被調(diào)度的

架構(gòu)簡述

圖片圖片

  1. 執(zhí)行器注冊到調(diào)度中心
  2. 頁面新建/修改job ->根據(jù)執(zhí)行策略計(jì)算 下次執(zhí)行時間
  3. 執(zhí)行線程輪詢表  5s 執(zhí)行job  -> 阻塞策略
  4. 記錄執(zhí)行信息 ->更新下次執(zhí)行

大家可以看到上圖是一個簡要的job執(zhí)行的流程圖 在了解代碼前和大家簡要的介紹一下XXLJOB的通信結(jié)構(gòu),調(diào)度中心和執(zhí)行器各維護(hù)一個netty的服務(wù),雙方使用HTTP通信,執(zhí)行器的ip和端口在啟動時會通過http調(diào)用通知調(diào)度中心,各位在啟動服務(wù)時是可以看到XXLJOB對應(yīng)的日志的,在看XXLJOB的代碼時大家會看到一些以client或impl結(jié)尾的實(shí)現(xiàn),對應(yīng)的就是調(diào)度中心和執(zhí)行器的netty的實(shí)現(xiàn)。

圖片圖片

下面筆者帶大家深入了解一下具體的代碼 在執(zhí)行器端需配置一些參數(shù),從而時執(zhí)行器能夠找到調(diào)度中心

圖片圖片

包括了調(diào)度中心的地址,執(zhí)行器的ip,端口(可以不填),日志的過期時間(非必填)

代碼詳解

  1. 啟動/初始化階段 在服務(wù)啟動時會啟動netty的服務(wù)
XxlJobSpringExecutor#afterSingletonsInstantiated()
->super.start()
->initEmbedServer();
->embedServer.start();
->startRegistry();
->ExecutorRegistryThread.getInstance().start()

最終啟動一個名為registryThread的線程,在這個線程中調(diào)用 adminBiz.registry()方法,調(diào)用調(diào)度中心的接口實(shí)現(xiàn)注冊 此時調(diào)度中心與執(zhí)行器(客戶端)就建立起了連接 此外在spring的bean初始化完成后 在XxlJobAdminConfig這個類中還利用afterPropertiesSet實(shí)現(xiàn)了初始化了一些線程

圖片圖片

這些線程的作用分別為處理國際化對應(yīng)的語言,快慢線程池的初始化,服務(wù)注冊監(jiān)控,任務(wù)執(zhí)行監(jiān)控,任務(wù)完成監(jiān)控,日志報表處理 ,任務(wù)執(zhí)行,限于篇幅,這些線程的作用我們下期再詳細(xì)的解釋,到現(xiàn)在為止,XXLJOB的啟動就已經(jīng)完成了。

  1. 頁面處理

圖片圖片

在調(diào)度中心的界面我們可以新建一個調(diào)度任務(wù),其中有幾個參數(shù)需要注意,jobhandler,運(yùn)行模式,阻塞策略,cron。由于目前大部分是在springboot中運(yùn)行的,所以大部分是依賴Bean執(zhí)行的,jobHandler則是代碼中定義的job名稱。運(yùn)行模式?jīng)Q定了調(diào)度中心選擇執(zhí)行器的邏輯

圖片圖片

阻塞策略決定了連續(xù)執(zhí)行時的策略

圖片圖片

cron則決定了調(diào)度的時間

  1. 執(zhí)行

下面我們深入了解一下一個job是如果被調(diào)度中心執(zhí)行的。執(zhí)行的邏輯在上文中提到的JobScheduleHelper中實(shí)現(xiàn)。首先會先獲取鎖,此處是利用mysql的for update實(shí)現(xiàn)的, 然后會獲取5秒內(nèi)的任務(wù)列表

圖片圖片

逐個遍歷拿到的任務(wù),如果任務(wù)已經(jīng)超過了執(zhí)行時間+預(yù)讀時間(5s),根據(jù)過期策略決定是丟棄還是立即執(zhí)行一次,并且更新下次執(zhí)行時間 如果當(dāng)前時間大于任務(wù)下次執(zhí)行時間,則將任務(wù)放入執(zhí)行線程池,等待執(zhí)行,更新下次執(zhí)行時間,如果下次執(zhí)行時間在5s內(nèi),則會將任務(wù)放入時間輪中,等待其他線程處理,再此更新此任務(wù)執(zhí)行時間如果均不是上述兩種情況,則會將任務(wù)放入時間輪中,更新執(zhí)行時間,等待其他線程處理。

for (XxlJobInfo jobInfo: scheduleList) {
    // time-ring jump
    if (nowTime > jobInfo.getTriggerNextTime() + PRE_READ_MS) {
        // 2.1、trigger-expire > 5s:pass && make next-trigger-time
        logger.warn(">>>>>>>>>>> xxl-job, schedule misfire, jobId = " + jobInfo.getId());
        // 1、misfire match
        MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(jobInfo.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING);
        if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) {
            // FIRE_ONCE_NOW 》 trigger
            JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.MISFIRE, -1, null, null, null);
            logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId() );
        }
        // 2、fresh next
        refreshNextValidTime(jobInfo, new Date());
    } else if (nowTime > jobInfo.getTriggerNextTime()) {
        // 2.2、trigger-expire < 5s:direct-trigger && make next-trigger-time
        // 1、trigger
        JobTriggerPoolHelper.trigger(jobInfo.getId(), TriggerTypeEnum.CRON, -1, null, null, null);
        logger.debug(">>>>>>>>>>> xxl-job, schedule push trigger : jobId = " + jobInfo.getId() );
        // 2、fresh next
        refreshNextValidTime(jobInfo, new Date());
        // next-trigger-time in 5s, pre-read again
        if (jobInfo.getTriggerStatus()==1 && nowTime + PRE_READ_MS > jobInfo.getTriggerNextTime()) {
            // 1、make ring second
            int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);
            // 2、push time ring
            pushTimeRing(ringSecond, jobInfo.getId());
            // 3、fresh next
            refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));
        }
    } else {
        // 2.3、trigger-pre-read:time-ring trigger && make next-trigger-time
        // 1、make ring second
        int ringSecond = (int)((jobInfo.getTriggerNextTime()/1000)%60);
        // 2、push time ring
        pushTimeRing(ringSecond, jobInfo.getId());
        // 3、fresh next
        refreshNextValidTime(jobInfo, new Date(jobInfo.getTriggerNextTime()));\
    }
}

具體執(zhí)行任務(wù)的方法是 com.xxl.job.admin.core.trigger.XxlJobTrigger#trigger

在這個方法中會根據(jù)執(zhí)行策略(ExecutorRouteStrategyEnum)選擇合適的執(zhí)行器,找到對應(yīng)的執(zhí)行器,利用netty的接口執(zhí)行對應(yīng)的任務(wù)

尾聲

在本期文章中,向大家介紹了XXLJOB是如何啟動和執(zhí)行任務(wù)的,在下期文章中將向大家介紹XXLJOB其他的細(xì)節(jié),由于一個定時任務(wù)系統(tǒng)的復(fù)雜,很多內(nèi)容還是需要各位讀者自己看一遍才能真正的理解,畢竟代碼才是真正的老師。

責(zé)任編輯:武曉燕 來源: 靈墨AI探索室
相關(guān)推薦

2024-08-27 09:34:24

2024-07-17 17:54:28

XXLJob分布式任務(wù)Java

2023-11-24 08:00:54

工具Go模板

2023-11-07 07:56:40

2013-12-17 10:15:19

OpenMP任務(wù)調(diào)度

2023-12-01 08:21:51

開發(fā)者Android組件庫

2023-12-29 09:38:00

Java線程池

2023-11-20 22:55:00

Goroutine調(diào)度器

2023-12-26 07:44:00

Spring定時調(diào)度

2023-11-22 13:18:02

Linux調(diào)度

2023-05-08 16:38:46

任務(wù)調(diào)度分布式任務(wù)調(diào)度

2010-06-23 16:09:40

Linux Bash

2025-04-07 04:00:00

教學(xué)型任務(wù)調(diào)度系統(tǒng)

2023-10-06 12:15:02

2020-05-18 10:27:06

框架EB級系統(tǒng)

2021-05-13 12:00:51

cron調(diào)度任務(wù)系統(tǒng)運(yùn)維

2022-09-16 11:23:59

Python框架Celery

2024-07-31 08:18:40

2020-04-01 16:10:02

PythonAPScheduler調(diào)度

2021-05-20 09:50:20

鴻蒙HarmonyOS應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號