簡介
再看一遍 xxl-job 架構圖:
調度中心主要提供了兩個功能: 系統管理 和 任務調度。其余的都是一些輔助功能。
- 系統管理正如圖中所示的那樣, 包括任務管理、執行器管理、日志管理。還提供了管理界面。
- 任務調度就是負責從數據中心拉取任務,並按照執行時間將任務投遞給執行器。
調度器的組成結構
兩個核心線程
當調度中心啟動后,會啟動以下兩個線程:
- schedulerThread
scheudlerThread
主要做如下兩件事情:
- 從數據中心(db),也就是
xxl_job_info
表中掃描出符合 條件 1 的任務, 條件1 限制如下:- 任務執行時間 小於(當前時間 + 5 s)
- 限制掃描個數, 這個值是動態的,會根據后面的提到的 快慢線程池 中線程數量有關系。
count = treadpool-size * trigger-qps (each trigger cost 50ms, qps = 1000/50 = 20) treadpool-size = (getTriggerPoolFastMax() + getTriggerPoolSlowMax()) * 20 // 看完快慢線程池的介紹,再回過頭來看這里,會更容易理解
- 掃描出來的任務被划分為以下 3 類:
- ringThread
ringThread
的作用就是不斷從 容器 中讀取 當前時間點需要執行 的任務, 讀取出來的任務會交給一個叫 快慢線程池 的東西去將任務傳遞給調度器去執行。
時間輪
上述的 ringThread
和 容器 共同組成了一個時間輪。
簡單來講,時間輪實現了 延遲執行 的功能,它在 xxl-job 中的作用就是讓 還未到達執行時間 的任務,按照預計的時間通過 快慢線程池 一個一個送到 執行器 中去執行。
-
時間輪的數據結構一般是 數組 + 鏈表, 和 jdk1.7 中的 HashMap 是一個道理,鏈表中的每個節點就是一個待執行的任務。
-
xxl-job 中的時間輪可以形象描述為以下這張圖,像一個只有秒針的鍾表一樣。
-
ringThread 線程運行過程中,每秒會掃過一個刻度,假設當前刻度位置存在 job 鏈表,就把鏈表中的所有 job 取出來,最后丟給 快慢線程池。
-
當然 xxl-job 為了避免處理耗時太長,會跨過刻度,多向前校驗一個刻度;也就是當指針指到 2s 時,會把 1s 和 2s 位置的任務同時讀取出來。
快慢線程池
上面提到任務從數據中心掃描出來后,隨之就會被丟到快慢線程池中,快慢線程池的定義如下:
fastTriggerPool = new ThreadPoolExecutor( 10, XxlJobAdminConfig.getAdminConfig().getTriggerPoolFastMax(), 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1000), new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode()); } }); slowTriggerPool = new ThreadPoolExecutor( 10, XxlJobAdminConfig.getAdminConfig().getTriggerPoolSlowMax(), 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(2000), new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "xxl-job, admin JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode()); } });
由上可知, 快慢線程池包含了兩個線程池 fast 和 slow,當一個 job 提交到快慢線程池后,快慢線程池會根據一些條件, 選擇其中一個線程池去執行后續的操作。
快慢線程池的作用如下:
實現線程池隔離:調度線程池進行隔離拆分,慢任務自動降級進入”Slow”線程池,避免耗盡調度線程,提高系統穩定性;
什么是慢任務?
如果一個任務在 1 分鍾內,它的執行超時次數超過 10 次,就被歸為 慢任務
當具體的快或者慢線程池接收到調度任務時,會通過 RPC 遠程調用去觸發 執行器 完成任務的執行邏輯。
源碼入口
com.xxl.job.admin.core.thread.JobScheduleHelper#start com.xxl.job.admin.core.thread.JobTriggerPoolHelper#addTrigger com.xxl.job.core.biz.client.ExecutorBizClient#run
總結
本文基於 xxl-job v2.x 的源碼分析了 xxl-job 調度器的組成結構 以及 調度中心是如何觸發任務的。
調度器主要包含了以下模塊:
- schedulerThread: 負責從數據中心掃描需要執行的任務
- ringThread: 負責精准地控制預計需要執行的任務
- 快慢線程池:通過包裝兩個線程池,去分別執行 快任務 和 慢任務 的調度過程。