您當前的位置:首頁 > 書法

噹噹分散式作業框架elastic-job解密(已開源)

作者:由 msup 發表于 書法時間:2018-09-19

原創: 張亮 壹佰案例

2017-06-27

噹噹分散式作業框架elastic-job解密(已開源)

導讀

ID:TOP100case 導語:基於成熟的開源產品Quartz和Zookeeper及其客戶端Curator二次開發的elastic-job,是一個分散式的作業排程框架。主要提供了可信賴的作業分散式叢集方案,並可以根據作業伺服器的執行狀況自動擴容縮容。本文將解密噹噹分散式作業框架elastic-job。

噹噹分散式作業框架elastic-job解密(已開源)

(全文共3766字 預計閱讀時長:4分鐘)

為什麼需要作業

作業即定時任務。一般來說,系統可使用訊息傳遞代替部分使用作業的場景。兩者確有相似之處。可互相替換的場景,如隊列表。將待處理的資料放入隊列表,然後使用頻率極短的定時任務拉取隊列表的資料並處理。

這種情況使用訊息中介軟體的推送模式可更好的處理實時性資料。而且基於資料庫的訊息儲存吞吐量遠遠小於基於檔案的順序追加訊息儲存。圖1所示為elastic-job分散式的作業排程框架。

噹噹分散式作業框架elastic-job解密(已開源)

圖1 elastic-job分散式的作業排程框架

但在某些場景下則不能互換:

時間驅動OR事件驅動

內部系統一般可以透過事件來驅動,但涉及到外部系統,則只能使用時間驅動。如:抓取外部系統價格。每小時抓取,由於是外部系統,不能像內部系統一樣傳送事件觸發事件。

批次處理OR逐條處理

批次處理堆積的資料更加高效,在不需要實時性的情況下比訊息中介軟體更有優勢。而且有的業務邏輯只能批次處理,如:電商公司與快遞公司結算,一個月結算一次,並且根據送貨的數量有提成。比如,當月送貨超過1000件,則額外給快遞公司多1%的快遞費。

非實時性OR實時性

雖然訊息中介軟體可以做到實時處理資料,但有的情況並不需要。如:VIP使用者降級,如果超過1年無購買行為,則自動降級。這類需求沒有強烈的時間要求,不需要按照時間精確的降級VIP使用者。

系統內部OR系統解耦

作業一般封裝在系統內部,而訊息中介軟體可用於系統間解耦。

噹噹之前使用的作業系統

噹噹之前使用的作業系統比較散亂,各自為戰,大致分為以下4種:

Quartz

Java事實上的定時任務標準。但Quartz關注點在於定時任務而非資料,並無一套根據資料處理而定製化的流程。雖然Quartz可以基於資料庫實現作業的高可用,但缺少分散式並行執行作業的功能。

TBSchedule

阿里早期開源的分散式任務排程系統。程式碼略陳舊,使用timer而非執行緒池執行任務排程。眾所周知,timer在處理異常狀況時是有缺陷的。而且TBSchedule作業型別較為單一,只能是獲取/處理資料一種模式。還有就是文件缺失比較嚴重。

Crontab

Linux系統級的定時任務執行器。缺乏分散式和集中管理功能。

Perl

遺留系統使用,目前已不符合公司的Java化戰略。

elastic-job的來歷

elastic-job原本是噹噹java應用框架ddframe(圖2所示)的一部分,本名dd-job。

ddframe包括編碼規範,開發框架,技術規範,監控以及分散式元件。ddframe規劃分為4個演進階段,目前處於第2階段。3、4階段涉及的技術元件不代表噹噹沒有使用,只是ddframe還未統一規劃。

噹噹分散式作業框架elastic-job解密(已開源)

圖2 噹噹java應用框架ddframe

ddframe由各種模組組成,均以dd-開頭,如dd-container,dd-soa,dd-rdb,dd-job等。噹噹希望將ddframe的各個模組與公司環境解耦並開源以反饋社群。之前開源的Dubbo擴充套件版本DubboX即是dd-soa的核心模組。而本次介紹的elastic-job則是dd-job的開源部分,其中監控(但開源了監控方法)和ddframe核心接入等部分並未開源。

elastic-job的功能

elastic-job主要的設計理念是無中心化的分散式定時排程框架,思路來源於Quartz的基於資料庫的高可用方案。但資料庫沒有分散式協調功能,所以在高可用方案的基礎上增加了彈性擴容和資料分片的思路,以便於更大限度的利用分散式伺服器的資源。主要功能如下:

4.1 分散式

最重要的功能,如果任務不能在分散式的環境下執行,那麼直接使用Quartz就可以了。

● 4.2 任務分片

是elastic-job中最重要也是最難理解的概念。任務的分散式執行,需要將一個任務拆分為n個獨立的任務項,然後由分散式的伺服器分別執行某一個或幾個分片項。

● 4.3 彈性擴容縮容

將任務拆分為n個任務項後,各個伺服器分別執行各自分配到的任務項。一旦有新的伺服器加入叢集,或現有伺服器下線,elastic-job將在保留本次任務執行不變的情況下,下次任務開始前觸發任務重分片。

舉例說明:有3臺伺服器,分為10個片。則分片項分配如下:

{server1: [0,1,2], server2: [3,4,5], server3: [6,7,8,9]}。

如果一臺伺服器崩潰,則分片項分配如下:

{server1: [0,1,2,3,4], server2: [5,6,7,8,9]}。

如果新增一臺伺服器,則分片項分配如下:

{server1: [0,1], server2: [2,3] , server3: [4,5,6] , server4: [7,8,9]}。

● 4.4 穩定性

在伺服器無波動的情況下,並不會重新分片;即使伺服器有波動,下次分片的結果也會根據伺服器IP和作業名稱雜湊值算出穩定的分片順序,儘量不做大的變動。

● 4.5 高效能

elastic-job會將作業執行狀態的必要資訊更新到註冊中心。如果作業執行頻度很高,會造成大量Zookeeper寫操作,而分散式Zookeeper同步資料可能引起網路風暴。因此為了考慮效能問題,可以犧牲一些功能,而換取效能的提升。

● 4.6 冪等性

elastic-job可犧牲部分效能用以保證同一分片項不會同時在兩個伺服器上執行。

● 4.7 失效轉移

彈性擴容縮容在下次作業執行前重分片,但本次作業執行的過程中,下線的伺服器所分配的作業將不會重新被分配。失效轉移功能可以在本次作業執行中用空閒伺服器抓取孤立作業分片執行。同樣失效轉移功能也會犧牲部分效能。

● 4.8 狀態監控

監控作業的執行狀態,可以監控資料處理功能和失敗次數,作業執行時間等。是冪等性,失效轉移必須的功能。

● 4.9 多作業模式

作業可分為簡單和資料流處理兩種模式,資料流又分為高吞吐處理模式和順序性處理模式,其中高吞吐處理模式可以開啟足夠多的執行緒快速的處理資料,而順序性處理模式將每個分片項分配到一個獨立執行緒,用於保證同一分片的順序性,這點類似於kafka的分割槽順序性。

● 4.10 其他功能

如錯過任務重執行,單機並行處理,容錯處理,Spring名稱空間支援,運維平臺等。

elastic-job的具體模組的底層及實現

elastic-job的主要分為註冊中心,資料分片,分散式協調,定時任務處理和多作業模式等模組。

● 5.1 註冊中心

模組目前直接使用zookeeper,用於記錄作業的配置,伺服器資訊以及作業執行狀態。Zookeeper雖然很成熟,但原理複雜,使用較難,在海量資料支援的情況下也會有效能和網路問題。

目前elastic-job已經抽象出注冊中心的介面,下一步將會考慮支援多註冊中心,如etcd,或由使用者自行實現註冊中心。無臨時節點和監聽機制的註冊中心需要自行實現定時心跳監測等功能。

● 5.2 資料分片

資料分片是elastic-job中實現分散式的重要概念,將真實資料和邏輯分片對應,用於解耦作業框架和資料的關係。作業框架只負責將分片合理的分配給相關的作業伺服器,而作業伺服器需要根據所分配的分片匹配資料進行處理。伺服器分片目前都儲存在註冊中心中,各個伺服器根據自己的IP地址拉取分片。

● 5.3 分散式協調

模組用於處理作業伺服器的動態擴容縮容。一旦叢集中有伺服器發生變化,分散式協調將自動監測並將變化結果通知仍存活的作業伺服器。協調時將會涉及主節點選舉,重分片等操作。目前使用的Zookeeper的臨時節點和監聽器實現主動檢查和通知功能。

● 5.4

定時任務處理

根據cron表示式定時觸發任務,目前有防止任務同時觸發,錯過任務重出發等功能。主要還是使用Quartz本身的定時排程功能,為了便於控制,每個任務都使用獨立的執行緒池。

● 5.5 多作業模式

將定時任務分為多種流程,有不經任何修飾的簡單任務;有用於處理資料的fetchData/processData的資料流任務;以後還將增加訊息流任務,檔案任務,工作流任務等。使用者能以外掛的形式擴充套件並貢獻程式碼。

elastic-job部署和使用

將使用elastic-job框架的jar/war連線同一個基於Zookeeper的註冊中心即可,如圖3所示。

作業框架執行資料並不限於資料庫,且作業框架本身是不對資料進行關聯的。作業可以用於處理資料、檔案、API等任何操作。

使用elastic-job所需要關注的僅僅是將業務處理邏輯和框架所分配的分片項匹配並處理,如:如果分片項是1,則獲取id以1結尾的資料處理。所以如果是處理資料的話,最佳實踐是將作業分片項規則和資料中間層規則對應。

噹噹分散式作業框架elastic-job解密(已開源)

圖3 elastic-job作業框架

對開源產品的開發理念

elastic-job的開源主要是為了反饋社群。開源短短兩個月,我們收到了很多朋友的反饋和支援,非常感謝。技術類開源專案和一般的業務型專案不同,更需要對程式碼和質量的控制,我們總結出以下幾點:

用心寫程式碼,用程式碼講故事。程式碼是專案的唯一核心和產出,任何一行的程式碼都需要用心思考優雅性、可讀性、合理性。

程式碼整潔乾淨到極致。簡單點說就是重視程式碼潔癖患者。只有程式碼漂亮整潔,其他開源愛好者才願意閱讀程式碼,進而找出專案中的bug和貢獻高質量程式碼。

極簡程式碼,高度複用,無重複程式碼和配置。Java生態圈的特點是高質量的開源產品極多。我們儘量考慮複用輪子,比如專案中大量用到lombok簡化程式碼;但也不會無原則的使用開源產品,我們傾向於把開源產品分為積木類和大廈類。專案中一般只考慮使用積木類搭建屬於我們自己的大廈,而不會直接用其他已成型的大廈。

單一需求可不考慮擴充套件性;兩個類似需求時再提煉。

模組抽象劃分合理。

如無特殊理由,測試需全覆蓋。elastic-job核心模組的測試覆蓋率是95%以上。雖然單元測試覆蓋率在分散式的複雜環境中並無太大說服力,但至少證明專案中很少出現低階邏輯錯誤。

對質量的定義。程式碼可讀性 > 程式碼可測性 > 模組解耦設計 > 功能正確性 > 效能 > 功能可擴充套件性。只有程式碼可讀,可測試,可100%掌控,專案才可持續發展。功能有缺陷可以修復,效能不夠可以最佳化,而程式碼不清晰則專案會漸漸變為黑盒。所以對於框架類產品,我們認為質量 > 時間 > 成本。

文件清晰。

未、來展望

目前的elastic-job定位是一個基於java的定時任務排程框架,未來想發展成為支援異構語言,高度靈活,可自定製的定時任務排程產品。

異構語言支援。目前採用的無中心設計,難於支援多語言,考慮排程中心的可行性。

監控體系有待提高,目前只能透過註冊中心做簡單的存活和資料積壓監控。未來需要做監控的部分有:

增加可監控維度,如作業執行時間等。

基於JMX的內部狀態監控。

基於歷史的全量資料監控,將所有監控資料透過flume等形式發到外部監控中心,提供實時分析功能。

多種註冊中心支援。

增加任務工作流,如任務依賴、初始化任務、清理任務等。

失效轉移功能的實時性提升。

更多作業型別支援,如檔案、MQ等型別作業的支援。

更多分片策略支援。

標簽: 分片  job  作業  Elastic  分散式