丁文婷 卜言彬
摘要:隨著信息化技術的不斷發(fā)展,微服務架構成為主流軟件開發(fā)架構,傳統(tǒng)的定時任務存在執(zhí)行效率低、容錯機制差、單點故障無法恢復、管理功能不完善等問題,已漸漸無法滿足業(yè)務需要。Elastic-Job分布式定時任務框架支持動態(tài)注冊微服務、分片執(zhí)行定時任務效率高、容錯機制完善、任務管理方便等優(yōu)點,為海量數據的互聯(lián)網應用開發(fā)提供了很好的解決方案。文章重點對Elastic-Job進行了研究并在互聯(lián)網企業(yè)級系統(tǒng)開發(fā)中進行實踐,提高了執(zhí)行的效率和準確率,并且達到了自動化運維的目的。
關鍵詞:定時任務;分布式;Elastic-Job;微服務;自動化運維
中圖分類號:TP399? ? ? 文獻標識碼:A
文章編號:1009-3044(2024)07-0033-04
開放科學(資源服務)標識碼(OSID)
0 引言
定時任務是指按照特定時間周期運行的任務。使用場景為在某個固定時間運行或者周期性地執(zhí)行某個任務,例如:每天24點做數據匯總,定時發(fā)送短信等[1]。傳統(tǒng)的定時任務在單臺服務器節(jié)點上進行部署,一旦因為網絡等原因造成的出錯,定時任務將停止執(zhí)行,這種單點部署的方式存在故障無法恢復、容錯機制較差等問題。隨著互聯(lián)網業(yè)務的興起,海量數據處理的定時任務需求越來越多,開發(fā)者對定時任務執(zhí)行效率的需求也在不斷提升,例如24點做數據匯總定時發(fā)短信的功能要在1小時內完成,若數據量過大,單個節(jié)點處理存在效率低下無法滿足要求的問題。分布式定時任務的出現(xiàn)很好地解決了以上問題,并提供了可視化界面管理定時任務。Elastic-Job分布式定時任務具有可彈性擴容、多線程處理定時任務效率高、失敗容錯機制好、具備冪等性等特點,適用于互聯(lián)網企業(yè)海量數據的應用系統(tǒng)服務開發(fā)。
1 定時任務框架比對
1.1 Quartz框架
Quartz是由OpenSymphony組織開發(fā)的開源且具有豐富特性的任務調度庫,主要由Job Detail、Job、Scheduler、Trigger 4個核心類構成[2]。Quartz能創(chuàng)建亦簡單亦復雜的調度,具備強大的調度功能與靈活的應用方式,但存在時間規(guī)則更改無法實時生效、缺乏容錯機制、沒有可視化管理界面等缺陷。
1.2 XXL-JOB框架
XXL-JOB將調度行為抽象成一個不承擔業(yè)務邏輯的調度中心公共平臺。平臺負責集中管理調度信息,依據調度配置進行調度請求,支持界面化動態(tài)配置、任務報警、任務新建、任務修改、任務刪除等管理功能,配置完成即刻生效。XXL-JOB通過執(zhí)行器統(tǒng)一管理拆分的多個JobHandler[3],依據接收到的調度請求,處理相應JobHandler中的業(yè)務模塊。這種將調度中心和執(zhí)行器分離的分布式定時任務框架實現(xiàn)了業(yè)務邏輯的解耦,提高了項目運行的穩(wěn)定性、代碼的可重用性以及系統(tǒng)的可擴展性。其缺點為依賴MySQL數據庫,集群越多鎖競爭越大。
1.3 Elastic-Job框架
Elastic-Job是當當網開源的分布式任務調度框架,用于解決分布式任務的協(xié)調調度問題,是面向互聯(lián)網生態(tài)和海量任務的適用于互聯(lián)網場景的分布式調度解決方案。Elastic-Job具有彈性調度、資源管控以及作業(yè)治理的功能,并通過開放的架構設計,提供多元化作業(yè)生態(tài)。Elastic-Job不依賴MySQL數據庫,不存在數據庫鎖競爭的問題。
上述三種定時任務框架的對比如表1所示。
2 Elastic-Job的研究
2.1 Elastic-Job的整體架構
Elastic-Job是基于Zookeeper、Quartz開發(fā)的Java分布式定時任務框架,解決了Quartz不支持分布式的問題。該框架主要的功能有支持彈性擴容、通過Zookeeper集中管理和監(jiān)控Job、支持失效轉移等。該項目由兩個相互獨立的子項目Elastic-Job-Lite和Elastic-Job-Cloud組成。
Elastic-Job-Lite定位為輕量級無中心化解決方案,以jar包的形式提供分布式任務的協(xié)調服務,其框架結構如圖1所示。
App服務器,也稱App節(jié)點,內含業(yè)務的定時任務,以jar的形式集成Elastic-Job-Lite相關組件,配置定時任務相關信息,可集群部署。
Elastic-Job-Lite負責作業(yè)的相關調度,產生任務調度記錄,Elastic-Job-Lite無中心化,每個節(jié)點的作業(yè)任務平等且自治,節(jié)點間通過注冊中心Registry進行分布式調度。
Registry以Zookeeper為注冊中心,利用Zookeeper可進行App節(jié)點的自動注冊和發(fā)現(xiàn)的功能特性,以文件的形式保存正在執(zhí)行的定時任務的基本信息,如IP、定時任務名稱、執(zhí)行時間等,同時利用節(jié)點中集成的Elastic-Job進行任務的實例選舉。Registry以REST API的形式提供接口供Console組件用于任務的運維管理。
Console為運維管理平臺,通過讀取Registry中的任務數據,展現(xiàn)任務的執(zhí)行狀態(tài)。運維可通過Console查看歷史執(zhí)行任務,修改任務的配置達到控制任務執(zhí)行的目的,且無須重啟App節(jié)點,支持定時任務修改熱生效。
Elastic-Job-Cloud使用Mesos+Docker的解決方案,額外提供資源治理、應用分發(fā)以及進程隔離等功能。
Elastic-Job-Cloud和Elastic-Job-Lite的功能對于定時任務的處理類似,區(qū)別如表2所示。
Elastic-Job-Cloud的優(yōu)勢在于Docker[4]部署,對資源細粒度的治理,非常適用于需要削峰填谷的大數據系統(tǒng)。
2.2 作業(yè)類型
Elastic-Job提供Simple、Dataflow和Script三種作業(yè)類型。
1) Simple類型。Simple作業(yè)類型未經任何封裝,開發(fā)者需實現(xiàn)SimpleJob接口,該接口僅提供execute方法用于任務處理,execute方法定時執(zhí)行,提供分片號等參數,開發(fā)者使用時與Quartz原生接口相似,利用分片號處理對應分片數據。
2) Dataflow類型。Dataflow作業(yè)類型用于處理數據流,需實現(xiàn)DataflowJob接口。該接口提供兩個方法可供實現(xiàn),分別用于抓取和處理數據,fetchDate方法抓取要處理的數據,processData方法處理抓取的數據。
3) Script類型。Script作業(yè)類型為腳本類型作業(yè),支持Shell、Python、Perl等類型腳本。開發(fā)者只需通過控制臺或代碼配置scriptCommandLine即可,無須編碼,執(zhí)行腳本路徑可包含參數,參數傳遞完畢后,作業(yè)框架自動追加最后一個參數作為作業(yè)運行時信息。
2.3 作業(yè)分片策略
非常耗時的定時任務,例如一次處理一億條數據,用一個節(jié)點可能要處理很久,在互聯(lián)網領域一般通過橫向擴展節(jié)點來縮短處理時長,Elastic-Job把作業(yè)分為多個分片任務,每個分片交給一個節(jié)點去執(zhí)行,一個節(jié)點可處理多個分片,每個分片的處理邏輯可由節(jié)點自身決定。
Elastic-Job提供三種任務分片策略,分別為平均分片策略、根據作業(yè)名的哈希值奇偶數決定IP升降序算法的分片策略、根據作業(yè)名的哈希值對服務器列表進行輪轉的分片策略。
平均分配策略為默認策略,也是使用最多的策略。假設有3個App節(jié)點處理同一個任務,若任務被分成0~8共9片,則每個App分到的分片為App1=[0,1,2],App2=[3,4,5],App3=[6,7,8]。若任務被分成0-7共8片,則每個App分到的分片為App1=[0,1,6],App2=[2,3,7],App3=[4,5]。若任務被分成0~9共10片,則每個App分到的分片為App1=[0,1,2,9],App2=[3,4,5],App3=[6,7,8]。由此可見,任務的執(zhí)行時間可縮短約三分之二。
此外分片策略支持自定義擴展,若考慮到App節(jié)點每臺的負載不同,開發(fā)者可自定義策略進行分片任務處理的調整。
2.4 Elastic-Job工作原理
Elastic-Job通過jar包形式集成到App節(jié)點,首個節(jié)點啟動后由監(jiān)聽器觸發(fā)主節(jié)點選舉,并使用鎖阻塞其他節(jié)點執(zhí)行任務,主節(jié)點選舉完畢后其他節(jié)點方能執(zhí)行任務。
任一節(jié)點啟動后節(jié)點信息被自動注冊到Zookeeper,節(jié)點下線時Zookeeper自動更新節(jié)點信息。主節(jié)點選舉、節(jié)點上下線、分片總數修改均更新重新分片標記,分片過程中若主節(jié)點下線,則先選舉主節(jié)點,再重新分片。
定時任務觸發(fā)時,節(jié)點首先檢查分片標記,若需要重新分片,則通過主節(jié)點重新分片,分片過程阻塞,結束后方能執(zhí)行任務。任務運行過程中只標記重新分片標記而不重新分片,下次任務執(zhí)行前重新分片。
節(jié)點執(zhí)行完任務后主動抓取未分配的分片任務,并在某節(jié)點下線后主動尋找可用的其他節(jié)點執(zhí)行分片,由此實現(xiàn)了分片任務的失效轉移,任務不停止執(zhí)行,從而提高容錯性。
2.5 失效轉移
Elastic-Job不在執(zhí)行過程中重新分片,而是等待下次調度之前才重新分片,當任務執(zhí)行過程中服務器宕機,Elastic-Job允許此次未完成的任務在另一任務節(jié)點上補償執(zhí)行。
失效轉移是當前執(zhí)行任務的臨時補償執(zhí)行機制,下次任務運行時,Elastic-Job通過重新分片對當前任務分配進行調整。開啟失效轉移功能,Elastic-Job將監(jiān)控作業(yè)每一分片的執(zhí)行狀態(tài),并將其寫入Zookeeper,供其他節(jié)點感知。
一次運行耗時較長且間隔較長的作業(yè)場景,失效轉移是提升作業(yè)運行實時性的有效手段。此外任務本身須具有冪等性,即故障轉移到新的節(jié)點上執(zhí)行時,業(yè)務數據不能重復執(zhí)行,已經執(zhí)行過的數據要在業(yè)務代碼上進行冪等性的處理,以保證失效轉移的正確性。
3 實踐和應用
3.1 項目功能描述
互聯(lián)網電商企業(yè)應用開發(fā)中,存在上百個微服務模塊處理不同的業(yè)務,如訂單、訂購、用戶、支付等不同模塊,每個模塊微服務以集群方式部署,某些定時任務如更新訂購關系狀態(tài)、更新訂單狀態(tài)等任務的處理耗時非常長,任務出錯后無法自動恢復,容錯機制差,運維工程師期望這些定時任務可通過統(tǒng)一的任務管理平臺進行查看和管理,因此引入Elastic-Job-Lite框架。
3.2 Zookeeper部署及其作用
本電商平臺Zookeeper部署在Linux環(huán)境下,安裝JDK1.8及Zookeeper3.6版本,在每個節(jié)點創(chuàng)建節(jié)點目錄、日志目錄以及myid文件。
Zookeeper是一個分布式一致性協(xié)調服務,是Apache Hadoop下的一個子項目,主要用來解決分布式應用中經常遇到的一些數據管理問題,如:統(tǒng)一命名服務、狀態(tài)同步服務、集群管理、分布式應用配置項的管理等。Zookeeper維護一個類似文件系統(tǒng)的樹形數據結構,其客戶端(如Elastic-Job任務執(zhí)行實例)可對數據進行讀取,每個子目錄項如“/app1”都被稱作znode目錄節(jié)點。Zookeeper和文件系統(tǒng)相同,可自由增加、刪除znode,可在znode下增加、刪除子znode,唯一的不同在于znode可存儲數據。
Zookeeper擁有數據監(jiān)聽通知機制,客戶端注冊監(jiān)聽znode,當znode發(fā)生變化,如數據改變、znode被刪除、子節(jié)點增加刪除時,Zookeeper通知所有客戶端。
Elastic-Job依賴于Zookeeper進行任務信息存儲和主節(jié)點選舉。任務信息包括任務名稱、任務實例節(jié)點信息、任務執(zhí)行策略。在任務的實例節(jié)點數量發(fā)生變化時,Elastic-Job重新觸發(fā)選舉機制。
3.3 微服務改造
本電商平臺微服務采用SpringBoot開發(fā),集成Elastic-Job時須在配置文件中配置任務相關信息和Zookeeper信息,微服務的定時任務處理時根據作業(yè)類型實現(xiàn)Elastic-Job提供的不同接口,Simple類型的作業(yè)實現(xiàn)SimpleJob接口,Dataflow類型的作業(yè)實現(xiàn)DataflowJob接口。
以訂購模塊的更新訂購關系狀態(tài)的任務為例,采用SimpleJob作業(yè)類型,集成Elastic-Job-Lite框架時,須修改以下信息。
1) 配置文件。配置文件須配置注冊中心Zookeeper信息以及定時任務相關參數,如:
elasticjob:
#注冊中心配置
regCenter:
#Zookeeper的ip和端口
serverLists: localhost:2181
#命名空間,模塊名命名分離不同模塊的任務
namespace: subscription
#定時任務配置
jobs:
#自定義的任務名稱
jobA:
#對應的類
elasticJobClass: com.cucn.job.JobA
cron: 0/10 * * * * ?
#自定義參數
jobParameter:
#分片總數
shardingTotalCount: 3
#自定義的分片參數
shardingItemParameters:
2) 作業(yè)任務代碼。訂單模塊的微服務中使用Simple類型的作業(yè)實現(xiàn)SimpleJob接口,通過ShardingContext類的getShardingItem方法獲取分片號,根據分片號獲取該分片要處理的數據并進行處理。例如根據分片號獲取訂單分表的數據,只須將分片號作為參數傳入表名獲取該分片對應的分表信息進行處理。
JobA代碼如下:
@Component
public class JobA implements SimpleJob {
private final Logger logger = LoggerFactory.getLogger(JobA.class);
@Autowired
private OrderService orderService;
@Override
public void execute(ShardingContext context) {
logger.info("JobA execute start...item: {}|param: {}",
context.getShardingItem(), context.getShardingParameter());
try{
// 通過分片號和參數獲取要處理的分表數據
List
// 處理數據
for (Order order: orders) {
orderService.setCompleted(order.getId());
}
}
catch(Exception e){
logger.error("JobA execute failed...item={},param={}",context.getShardingItem(), context.getShardingParameter(),e);
}
finally{
logger.info("JobA execute end...");
}
}
}
3.4 任務管理系統(tǒng)的搭建
為方便運維管理各個模塊所有處理海量數據的定時任務,本系統(tǒng)須搭建運維統(tǒng)一管理平臺Console,該子系統(tǒng)提供可視化界面供運維統(tǒng)一管理定時任務,通過該系統(tǒng)調用注冊中心API,可查看和修改任務,任務失敗可重新執(zhí)行,無須重啟App節(jié)點。該運維統(tǒng)一管理平臺界面如圖2所示。
Console運維管理平臺后端采用Java語言,前端采用HTML、CSS、JS等語言開發(fā),數據庫采用MySQL8來持久化作業(yè)信息,工程管理工具Maven,集成后將其部署到Linux環(huán)境下。
首次搭建Console管理平臺需設置全局配置,設置注冊中心名稱和地址等信息。啟動應用后可在Console中查看作業(yè)的運行情況。
Console管理平臺提供服務器維度和作業(yè)維度查看任務的功能。服務器維度可查看接入了Elastic-Job的服務器IP、進程號、運行實例等信息;作業(yè)維度可查看各個服務器的定時任務作業(yè)名稱、作業(yè)分片總數、作業(yè)運行的時間、作業(yè)狀態(tài)等信息。
Console管理平臺可修改作業(yè)的信息,服務器維度可將服務器禁用,停止該服務器的定時任務執(zhí)行,作業(yè)維度可修改作業(yè)信息,如通過cron表達式修改定時任務的執(zhí)行時間、修改分片總數、新增自定義參數等,運維工程師只需找到作業(yè)名稱修改其作業(yè)信息即可,修改作業(yè)界面如圖3所示。
Console運維管理平臺還可查看任務的歷史調度信息、執(zhí)行參數和執(zhí)行信息,進入Console可查看執(zhí)行日志[5],清晰地掌握每臺服務器定時任務的歷史執(zhí)行時長、執(zhí)行結果。
4 結論
本文重點介紹了Elastic-Job分布式定時任務框架的研究并概述了某大型互聯(lián)網應用系統(tǒng)上的實踐,通過使用Elastic-Job解決了互聯(lián)網企業(yè)在大數據量定時任務作業(yè)中處理效率低、容錯性差、任務管理不方便等問題,同時保證了系統(tǒng)的高可用性、伸縮性、負載均衡,并提高了容錯性。Elastic-Job框架讓開發(fā)者不再擔心任務的線性吞吐量提升等非功能需求,使開發(fā)者能夠更加專注于業(yè)務編碼設計,同時Elastic-Job可提高運維工程師的工作效率,使運維不再擔心任務的可用性和相關管理需求,只需通過可視化界面操作相關App節(jié)點即可輕松管理處理海量數據的定時任務,從而達到了自動化運維的目的。
參考文獻:
[1] 陸穎.基于XXL-JOB的可視化分布式定時調度平臺的設計與實現(xiàn)[J].電腦知識與技術, 2023,19(14):39-41.
[2] 屈洪雪,陳雙,徐海洋.基于Quartz的可視化代理定時任務的研究與設計[J].電子技術與軟件工程,2021(18):44-46.
[3] 鄭祥,顧丹鵬,陳肖勇.基于XXL-JOB的分布式定時任務研究和應用[J].計算機時代,2002(5):80-82.
[4] 段詡,張文輝.基于Docker集群的分布式動作教學平臺設計[J].電子設計工程,2020,28(23):63-67,72.
[5] 潘平平.基于松耦合架構的分布式定時任務調度系統(tǒng)的設計與實現(xiàn)[D].南京:東南大學,2020.
【通聯(lián)編輯:王 力】