主流定時任務解決方案全橫評
定時任務作為一種按照約定時間執行預期邏輯的通用模式,在企業級開發中承載著豐富的業務場景,諸如後臺定時同步資料生成報表,定時清理磁碟日誌檔案,定時掃描超時訂單進行補償回調等。程式開發人員在定時任務領域有著諸多框架和方案可供選擇,並藉此快速實現業務功能實現產品上線。本文將就當前主流定時任務解決方案進行介紹和分析,期望可以在企業技術選型和專案架構重構時作為參考。
01
Crontab
Aliware
01
目標定位
Crontab 作為 Linux 內建的可執行命令,可以實現按照 cron 表示式生成的時間執行指定的系統指令或 shell 指令碼。
02
使用方式
crontab 命令語法:
crontab [-u username] [-l | -e | -r ]
引數:
-u : 只有root使用者才能進行這個任務,編輯某個使用者的crontab
-e : 編輯 crontab 的工作內容
-l : 查閱 crontab 的工作內容
-r : 移除所有的 crontab 的工作內容
配置檔案示例:
* * * * * touch ~/crontab_test
* 3 * * * ~/backup
0 */2 * * * /sbin/service httpd restart
03
實現原理
crond 守護程序是通過 Linux 啟動時的 init 程序啟動,由 cornd 每分鐘會檢查/etc/crontab 配置檔案中是否有需要執行的任務,並通過 /var/log/cron 檔案輸出定時任務的執行情況。使用者可以使用 Crontab 命令管理/etc/crontab 配置檔案。
04
方案分析
藉助 Crontab 使用者可以十分便利的快速實現簡易的定時任務功能,但存在以下痛點:
-
定時任務與指定 linux 機器繫結,當機器擴容或者更換時需要重新配置 contab,同時存在單點故障風險
-
隨著定時任務規模增多,無統一視角對其進行任務進度的追蹤和管控,難以維護
-
功能過於簡單,沒有超時,重試,阻塞等任務高階特性
-
可觀測能力差,問題排查定位困難
-
任務常駐,當無任務執行時造成不必要的資源成本浪費
02
Spring Task
Aliware
01
目標定位
Spring 框架提供了開箱即用的定時排程功能,使用者可以通過 xml 或者@Scheduled 註解的方式標識指定方法執行的週期。Spring Task 支援多種任務執行模式,包括帶時區配置的 corn,固定延遲,固定速率等。
02
使用方式
程式碼例項如下:
@EnableScheduling
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
@Component
public class MyTask {
@Scheduled(cron = "0 0 1 * * *")
public void test() {
System.out.println("test");
}
}
03
實現原理
Spring Task 的原理是在初始化 bean 時藉助 ScheduledAnnotationBeanPostProcessor 攔截@Scheduled 註解所標識的方法,並根據每個方法及其註解配置構建相應的 Task 例項註冊到 ScheduledTaskRegistrar 中,並在單例 bean 初始化完成後通過 afterSingletonsInstantiated 回撥設定 ScheduledTaskRegistrar 中的排程器 TaskScheduler,其底層依賴於 jdk 併發包中的 ScheduledThreadPoolExecutor 實現,並在 afterPropertiesSet 時將所有 Task 新增到 TaskScheduler 中排程執行。
04
方案分析
藉助 Spring Task 使用者可以通過註解快速實現對指定方法的週期性執行,支援多種週期性策略。但與 crontab 相似,同樣有如下的痛點:
-
預設為單執行緒執行,若前一個任務執行時間較長會導致後續任飢餓阻塞,需要使用者自行配置執行緒池
-
各個節點獨立執行,存在單點風險,無分散式協調機制,要考慮禁止併發執行
-
隨著定時任務規模增多,無統一視角對其進行任務進度的追蹤和管控,難以維護
-
功能過於簡單,沒有超時,重試,阻塞等任務高階特性
-
可觀測能力差,問題排查定位困難
-
任務常駐,當無任務執行時造成不必要的資源成本浪費
03
ElasticJob
Aliware
01
目標定位
ElasticJob 作為噹噹網開源的一款分散式任務框架,提供彈性排程,資源管控,作業治理等諸多特性,其已經成為 Apache Shardingsphere 的子專案。ElasticJob 目前由 2 個相互獨立的子專案 ElasticJob-Lite 和 ElasticJob-Cloud 組成,ElasticJob-Lite 定位為輕量級無中心化解決方案,使用 jar 的形式提供分散式任務的協調服務;ElasticJob-Cloud 使用 Mesos 的解決方案,額外提供資源治理、應用分發以及程序隔離等服務。一般使用 ElasticJob-Lite 即可滿足需求。
02
使用方式
使用者需要在 yaml 中配置註冊中心 zk 的地址以及任務的配置資訊:
elasticjob:
regCenter:
serverLists: localhost:6181
namespace: elasticjob-lite-springboot
jobs:
simpleJob:
elasticJobClass: org.apache.shardingsphere.elasticjob.lite.example.job.SpringBootSimpleJob
cron: 0/5 * * * * ?
timeZone: GMT+08:00
shardingTotalCount: 3
shardingItemParameters: 0=Beijing,1=Shanghai,2=Guangzhou
實現對應的介面即可標識對應的任務,同時通過配置監聽器來實現任務執行前後回撥:
public class MyElasticJob implements SimpleJob {
@Override
public void execute(ShardingContext context) {
switch (context.getShardingItem()) {
case 0:
// do something by sharding item 0
break;
case 1:
// do something by sharding item 1
break;
case 2:
// do something by sharding item 2
break;
// case n: ...
}
}
}
public class MyJobListener implements ElasticJobListener {
@Override
public void beforeJobExecuted(ShardingContexts shardingContexts) {
// do something ...
}
@Override
public void afterJobExecuted(ShardingContexts shardingContexts) {
// do something ...
}
@Override
public String getType() {
return "simpleJobListener";
}
}
03
實現原理
ElasticJob 底層時間排程基於 Quartz,Quartz 需要持久化業務 Bean 到底層資料表中,系統侵入性相當嚴重,同時通過 db 鎖進行任務搶佔,不支援並行排程,不具備可擴充套件性。而 ElasticJob 通過資料分片以及自定義分片引數的特性完成了水平擴充套件,可以將一個任務拆分為 N 個獨立的任務項,由分散式的伺服器並行執行各自分配到的分片項。比如一個數據庫中有 1 億條資料,需要將這些資料讀取出來並進行計算,就可以將這 1 億條資料劃分成 10 個分片,每一個分片讀取其中的 1 千萬條資料,然後計算後寫入資料庫。如果有三臺機器執行,A 機器分到分片(0,1,2,9),B 機器分到分片(3,4,5),C 機器分到分片(6,7,8),這也是相比於 Quartz 最顯著的優勢。
實現上 ElasticJob 使用 zookeeper 作為註冊中心進行分散式排程協調以及 leader 節點的選舉,通過註冊中心的臨時節點的變化來感知伺服器的增減,每當 leader 節點選舉,伺服器上下線,分片總數變更時均會觸發後續的重新分片,由 leader 節點在下次定時任務觸發時進行具體的分片劃分,再由各節點從註冊中心中獲取分片資訊,作為任務的執行引數進行執行。
04
方案分析
ElasticJob 作為分散式任務框架,解決了上述單節點任務無法保證任務執行過程中的高可用和高併發下執行的效能的問題,並支援失敗轉移(failover)和錯過執行的作業重新執行(misfire)等高階機制,但在使用過程中仍存在以下痛點:
-
框架整體較重,需要依賴外接註冊中心zk,增加了至少三臺伺服器的使用成本和維護複雜度
-
隨著任務量的不斷增多,zk 作為有狀態中介軟體將會成為效能瓶頸
-
可觀測能力弱,需要額外引入 db 並配置事件追蹤
-
任務常駐,當無任務執行時造成不必要的資源成本浪費
04
XXLJob
Aliware
01
目標定位
XXLJob 作為大眾點評員工開源的一款分散式任務框架,其核心設計目標是開發迅速、學習簡單、輕量級、易擴充套件。XXLJob 具備豐富的功能,如任務分片廣播,超時控制,失敗重試,阻塞策略等,並通過體驗友好的白屏化控制檯對任務進行管理和維護。
02
使用方式
XXLJob 分為中心式排程器和分散式執行器兩部分組成,在使用時需要分別啟動,在排程中心啟動時需要配置所依賴的 db 配置。
執行器需要配置排程中心的地址:
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=
xxl.job.executor.appname=xxl-job-executor-sample
xxl.job.executor.address=
xxl.job.executor.ip=
xxl.job.executor.port=9999
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
xxl.job.executor.logretentiondays=30
通過 bean 模式方法形式建立任務和前後回撥的使用方式如下:
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
public void demoJobHandler() throws Exception {
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
XxlJobHelper.log("分片引數:當前分片序號 = {}, 總分片數 = {}", shardIndex, shardTotal);
}
public void init(){
logger.info("init");
}
public void destroy(){
logger.info("destory");
}
建立任務完成後,需要在控制檯上配置任務的執行策略:
03
實現原理
XXLJob 實現上將排程系統與任務解耦,其自研排程器負責管理排程資訊,按照排程配置發出排程請求,支援視覺化、簡單且動態的管理排程資訊,自動發現和路由,排程過期策略,重試策略,支援執行器 Failover。執行器負責接收排程請求並執行任務邏輯,並接收任務終止請求和日誌請求,負責任務超時,阻塞策略等。排程器和執行器通過 restful api 進行通訊,排程器本身無狀態支援叢集部署,提升排程系統容災和可用性,通過 mysql 維護鎖資訊和持久化。執行器無狀態支援叢集部署,提升排程系統可用性,同時提升任務處理能力。
XXLJob 一次完整的任務排程通訊流程:首先排程中心向執行器內嵌 Server 傳送 http 排程請求,然後執行器執行對應的任務邏輯,待任務執行完成或超時後執行器傳送 http 回撥向排程中心返回排程結果。
04
方案分析
XXLJob 在開源社群廣泛流行,憑藉其簡單的操作和豐富的功能已在多家公司投入使用,可以較好的滿足生產級別的需求,但下面的一些痛點需要改進:
-
需要依賴外接 DB,增加了資料庫的使用成本和維護複雜度
-
依賴 DB 鎖保證叢集分散式排程的一致性,當短時任務量不斷增多將對 db 造成較大壓力,成為效能瓶頸
-
相較於無中心模式需要額外部署排程器,排程器和執行器均需要常駐同時為保證高可用均至少兩臺,當無任務執行時造成不必要的資源成本浪費
05
Serverless Job
Aliware
01
目標定位
Serverless 作為雲端計算的最佳實踐和未來演進趨勢,其全託管免運維的使用體驗和按量付費的成本優勢使得其在雲原生時代備受推崇。SAE (Serverless 應用引擎)Job 作為首款面向任務的 Serverless PaaS 平臺,提供傳統的使用者體驗。當前聚焦支援單機、廣播、並行分片模型的任務,同時支援事件驅動、併發策略和超時重試等諸多特性,提供低成本、多規格、高彈性的資源例項來滿足短時任務的執行。
02
使用方式
對於使用上述所有方案的存量應用,SAE (Serverless 應用引擎) Job 在相容功能體驗的同時支援零改造無感遷移,無論使用者使用的是 Crontab,Spring Task,還是 ElasticJob, XXLJob,均可將程式碼包或者映象直接部署到 SAE (Serverless 應用引擎) Job中,直接升級成為 Serverless 架構, 從而即刻擁有 Serverless 所帶來的技術上的優勢,節省資源成本和運維成本。
對於運完即停的程式,無論是 Java,還是 Shell,Python,Go,Php 均可以直接部署到 SAE (Serverless 應用引擎) Job 中, 從而即刻擁有白屏化管控,全託管免運維的完備體驗以及開箱即用的可觀測功能。
03
實現原理
SAE (Serverless 應用引擎)Job 底層為多租 Kubernetes,使用神龍裸金屬安全容器、VK 對接 ECI 兩種方式提供叢集計算資源。使用者在 SAE(Serverless 應用引擎)中執行的任務會對映到 Kubernetes 中相應的資源。其中多租能力是藉助系統隔離、資料隔離、服務隔離和網路隔離實現租戶間的隔離。SAE (Serverless 應用引擎)Job 通過 Event Bridge 作為事件驅動源,在支援豐富呼叫方式的同時避免了 Kubernetes 內建定時器不保證準時觸發以及精度時區上的問題。同時不斷完善 Job 控制器的企業級特性,新增自定義分片,注入配置,差異化 GC,sidecar 主動退出,實時日誌持久化,事件通知等機制。並藉助 Java 位元組碼增強技術接管任務排程,實現通用的 Java 目標框架的零改造 Serverless 化。使用 KubeVela 軟體交付平臺作為任務釋出和管理的載體,以任務為中心,以開源開放的標準,通過宣告式的方式完成整個雲原生交付。SAE (Serverless 應用引擎)Job 將持續優化 etcd 以及排程器在短時任務高併發建立場景下的效率以及例項啟動的極致彈效能力,結合彈性資源池保證任務排程的低延遲和高可用。
04
方案分析
SAE (Serverless 應用引擎)Job 解決了上述定時任務解決方案的各種痛點,使用者無需關注任務的排程和叢集資源,無需部署的額外的運維依賴元件,也無需自建一整套監控告警系統,同時更重要的是無需雲主機 7*24h 常駐,在低資源利用率的環境下持續消耗閒置資源。
SAE (Serverless 應用引擎)Job 相較於傳統定時任務解決方案提供了三大核心價值:
-
完備全託管:提供了一站式全託管的管理介面,其任務生命週期管理、可觀測性開箱即用,使用者可以低心智負擔、零成本地學習使用 SAE (Serverless 應用引擎)。
-
簡單免運維:遮蔽了底層資源,使用者只需關注其核心的業務邏輯開發,無需操心叢集可用性、容量、效能等方面的問題。
-
超高性價比:採用按需使用、按量付費的模式,只有任務執行業務邏輯時才會拉起收費,其餘時間不收取任何費用,極大節省了資源的成本開銷。
06
總結
Aliware
本文對主流定時任務解決方案(Crontab, Spring Task, ElasticJob, XXLJob, Serverless Job)的目標定位、使用方式、實現原理進行了闡述,同時就企業密切關注的功能體驗,效能成本方面的問題進行橫評分析。最後期望大家選用 Serverless Job,感受其對傳統任務所帶來的新變革。
點選下方瞭解更多 SAE Job 的功能優勢,和眾多開源任務框架“低門檻”遷移的方案!
- 如何使用 rust 寫核心模組
- Dubbo 在 Proxyless Mesh 模式下的探索與改進
- 工作一年,我重新理解了《重構》
- 談談我對於關鍵思考的理解
- 談談我工作中的23個設計模式
- 談談我工作中的23個設計模式
- Serverless 奇點已來,下一個十年將駛向何方?
- 阿里巴巴重磅開源雲原生閘道器: Higress
- 我們總結了 3 大使用建議,並首次公開 Nacos3.0 規劃圖 | Nacos 開源 4 週年
- SAE 助力貴州酒店集團從容支撐貴州特產搶購
- 甩掉容量規劃炸彈:用 AHPA 實現 Kubernetes 智慧彈性伸縮
- 聊聊降本提效這件事兒
- 主流定時任務解決方案全橫評
- 通過Jenkins構建CI/CD實現全鏈路灰度
- 一站式動態多環境建設案例
- Proxyless Mesh 在 Dubbo 中的實踐
- ChaosBlade Java 場景效能優化,那些你不知道的事
- 新零售標杆 SKG 全面擁抱 Serverless,實現敏捷交付
- 「技術人生」第9篇:如何設定業務目標
- 面向物件分析與設計的底層邏輯