歡迎光臨
每天分享高質量文章

點我達分佈式任務調度系統-DaJob

點擊上方“芋道原始碼”,選擇“置頂公眾號”

技術文章第一時間送達!

原始碼精品專欄

 

來源:點我達技術團隊

背景

    隨著互聯網的發展,應用服務中的定時任務數量日益增加,常規的垂直應用架構已無法應對,分佈式服務架構勢在必行。同時,也迫切需要一個分佈式任務調度系統來管理分佈式服務中的定時任務。

單一應用架構

    當網站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節點和成本。此時,在該應用中的定時任務如果不多還好,但是一旦比較多,則意味著每次更改一個定時任務的執行時間,就需要重新部署一遍整個應用,導致整個應用停滯一段時間。

垂直應用架構

    當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆分為互不相干的幾個應用來提升效率。此時,相應的任務也會被垂直拆分,每次更改任務帶來的影響相應減少。

分佈式服務架構

    當垂直應用越來越多,應用之間可能會出現不可避免的交互,此時,將核心業務抽取出來,形成單獨的服務,各式各樣的服務逐漸形成穩定的服務中心,使得前端應用能更快地響應多變的市場需求。此時,用於提高業務復用及整合的分佈式服務框架是關鍵,同時,由於服務獨立,則一般能做到定時任務獨立的情況,因此,任務的更改對於整體系統的影響小之又小。

分佈式任務調度

    在分佈式服務架構的基礎上,由於獨立業務的數量可能很多,此時如果定時任務單獨在該服務中實現,很可能會出現難以管理的情況,且避免不了定時任務更改導致的業務重啟,因此,一個獨立的分佈式任務調度系統是很必要的,可以用來全域性統籌管理所有的定時任務,同時,將任務的配置單獨抽離出來作為該分佈式任務調度系統的功能,就能做到定時任務的更改不影響任何業務,也不影響整個系統。

架構設計

設計思想

    以Dubbo核心,將調度單獨抽象出來,成為一個調度中心,調度中心本身不承擔實現任何業務邏輯,只是單純依據調度配置來發起調度請求
    將任務抽象成為ExecutorService,由任務執行者來實現具體的任務,並且負責接收調度請求並執行,這樣設計可以將任務與調度中心完全解耦,提高整個系統的擴展性,方便接入
    將調度中心對任務執行者的一些呼叫操作提取出來,形成一個單獨的管理控制台,可以用來查看任務執行情況,同時該管理控制台通過H5實現,並提供對外Restful API,方便擴展與接入
    通過各種中間件,實現一些必須的操作,例如告警,監控,日誌收集統計等操作,完全對整個系統安全性,穩定性的保障

  調度中心集群通過Zookeeper儲存每個Schedular的一致性HashCode,以此來分配Job與Schedular之間的關係:新增的Job將會通過每個Schedular的一致性HashCode獲取其對應的Job數,依據Job數的大小以及Schedular的相關屬性來計算每個Schedular的權重,根據權重的大小來確定當前新增的Job應該被分配到哪個Schedular上。
    當新增Schedular之後,該新增的Schedular的Job正常為0,因此,正常狀態下,該新增的Schedular的權重會比較大。
    同時,調度中心通過Zookeeper對Schedular實現主備切換,確保系統穩定性

系統組成

Schedular

    基於Quartz實現調度,提供對執行者操作的接口,用於操作任務調度配置,調度觸發等操作;自身不參與任務邏輯的實現,不會受限於任務

執行者

    負責接收調度中心發起的調度請求,實現相應業務邏輯,完成任務執行,同時會對任務邏輯進行切麵處理,記錄相應日誌併在任務結束後發送給調度中心

管理控制台

    管理控制台負責展示任務狀態,執行情況,任務執行日誌等報表資料,同時可以通過管理控制台配置新增任務,操作任務的狀態,暫停/恢復等;另外,提供對外Restful API與H5的接入

Dubbo Monitor

    實時監控調度中心接口呼叫情況,統計調度頻次,成功失敗,QPS等,能通過這些報表資料來優化任務調度,優化系統

ELK

    通過ELK(ElasticSearch+Logstash+Kibana)來收集調度中心以及各執行機的執行日誌,並加以分析統計,形成報表,可以方便提供觀察

Alarm

    報警系統,通過Chronograf控制台配置告警規則,在出現問題時第一時間通過Kapacitor進行郵件與短信報警,可以有效提高錯誤提示的及時性並且降低錯誤發生到錯誤解決過程中消耗的時間,降低生產環境造成的損失,告警資料通過業務儀錶盤獲取。例如:可以配置線上機器的cpu當前使用率,設置閥值50%,策略為超過設置閥值時短信告警,此時當線上某台機器cpu超過50%時,即會發送短信告警

業務儀錶盤

    通過打點的方式,來實時收集接口監控資料,通過logstash傳輸到kafka,通過kafka再分發到jstorm進行處理,處理完之後再儲存到influxdb,形成業務儀錶盤,最後通過Grafana控制台產生監控報表

配置中心

    整個系統各服務,通過配置中心統一管理相應配置,形成分佈式配置管理機制,方便系統內各服務的配置一致性以及準確性

 

   在使用上,對於接入者而言,只需做一些簡單的配置即可接入,接入界面簡單易懂

 在配置完之後,就可以實現自己的任務邏輯了

接入之後,可以通過日誌管理控制台線上實時查看任務執行狀態

    另外,由於有告警系統,在任務執行異常時,會產生告警郵件與短信,實時發送,告知任務接入者與相應研發人員
  配置中心屬性配置

特性

   支持動態暫停/恢復任務

    任務狀態停止時,任務將不再被觸發,若任務在執行過程中被暫停,則正在執行的任務不會被阻塞(由於任務執行結果狀態中存在超時失敗狀態,因此如果點擊暫停按鈕時阻塞了當前正在執行的任務,會使當前任務的執行狀態變為超時,不符合超時狀態真正的意義),會延遲停止,即等到當前任務執行完再真正停止任務
    調度中心基於Quartz實現,通過Zookeeper實現主備隔離,保證調度中心HA
     當活躍節點宕機,冷備節點就會載入所有活躍節點中正在調度狀態的任務,成為新的活躍節點,保證任務調度的準確執行
    執行機支持集群部署,任務分佈式執行,通過調度中心統一調度
     執行機負載均衡,預設根據任務在某個執行機上的執行次數計算執行機調度權重,按照權重來選擇本次任務調度分發給哪台執行機,實現負載均衡,可手動更改執行機選擇策略

執行機集群方式,

failover,failfast,failsafe,failback,forking,預設為failover(故障切換),呼叫失敗時,重試其他服務器;failfast(快速失敗),只會發起一次呼叫,不會重試,失敗立即報錯;failsafe(失敗安全),出現異常時,直接忽略;failback(失敗恢復),呼叫失敗時,定時重發,直到成功,重啟會丟失; forking,並行呼叫多個執行機,只要一個成功即傳回

   分片任務,支持任務分片,通過引數發送給任務執行機,執行機可以通過判斷引數來進行分片作業的開發,同時支持動態分片,以分片引數和執行機為緯度進行分片,支持動態擴容執行機以及分片引數

    例如,某張訂單表按照訂單ID來進行簡單緯度分片,且以取模3來進行分片,則可以設置三個分片引數,(0,1,2),執行機在通過context拿到其中的一個分片引數之後可以對該分片引數做判斷,來做具體的資料操作,例如當拿到的分片引數為0時,則對於0相應的分片做資料查詢操作,依次類推
    再例如,某張訂單表按照訂單ID和Status來進行二維分片,ID取模以3來進行分片,狀態以成功,失敗兩種狀態來進行分片,此時就可以設置6個分片引數,({‘id’:0,’status’:0},{‘id’:1,’status’:0},{‘id’:2,’status’:0},{‘id’:0,’status’:1},{‘id’:1,’status’:1},{‘id’:2,’status’:1}),執行機在通過context拿到其中的一個分片引數之後,就可以對其json引數進行判斷,來實現分片操作

   任務執行一致性,每次任務只會被一個執行機所執行;對於分片任務,在執行機集群部署時,一次任務調度將會廣播觸發對應集群中相應數量的執行器執行一次任務,同時傳遞分片引數,可根據分片引數開發分片任務。

    當分片引數大於執行器數量時,將會按照執行器路由策略,使得當前分片任務的某個或者某幾個執行機執行多個分片的任務

    例如:當前分片任務分片引數為(a,b,c),當前任務執行機有3台(A,B,C)時,則會均勻隨機得將分片引數發送給某一臺執行機,且三台執行機一次只接收一個分片引數,做一次任務處理,即(a->A,b->B,c->C)|(a->A,b->C,c->B)|(a->B,b->A,c->C)|(a->B,b->C,c->A)|(a->C,b->A,c->B) |(a->C,b->B,c->A);

     當任務執行機只有2台(A,B)時,每次任務調度時,某台執行機會收到兩個分片引數,並分別處理這兩個分片引數,即(a->A,b->B,c->A)|(a->A,b->B,c->B)|(a->B,b->A,c->A)|(a->B,b->A,c->B);

     而當任務執行機大於分片引數個數,為4台(A,B,C,D)時,(a->A,b->B,c->C)|(a->A,b->C,c->D)|(a->A,b->D,c->B)| (a->B,b->C,c->D)|(a->B,b->D,c->A)|(a->B,b->A,c->C)|(a->C,b->A,c->B)|(a->C,b->B,c->D)| (a->C,b->D,c->A)|(a->D,b->A,c->B)|(a->D,b->B,c->C)|(a->D,b->C,c->A),而統計下來,不管是執行機數目大於或者等於或者小於分片引數數目,被分發給執行機的分片引數始終是保持一致的(每台執行機接收到的總的分片引數是均勻的)

    告警系統,系統接入內部告警系統,任務失敗時支持郵件,短信,釘釘,電話等告警

    彈性擴容縮容,調度中心將會實時探測任務執行機,因此一旦有執行機上線或者下線,都將會被探測到,而如果未被調度中心探測到,則可以進行手動探測執行機,而在探測到執行機之後,下次調度將會重新分配任務
    任務依賴,支持配置任務依賴關係,當父任務在執行完成之後會自動觸發子任務的執行
例如:有兩個任務,分別為A和B,而B的執行條件為確認A任務執行完,B才能執行,否則,B任務不執行,此時的依賴關係就是B任務依賴A任務,此時在A任務配置完之後,設置B任務為依賴任務,而依賴關係則是A;又例如有6個任務,分別是A1,A2,A3,A4,A5,B,而B任務的執行需要確保A1-5這5個任務都執行完,B任務才執行,此時,B的依賴關係就是B任務依賴於A1-5,此時在配置完A1-5這5個任務之後再設置B為依賴任務,依賴關係則是A1-5 

    支持運行時查看任務執行情況,任務數量,呼叫次數,執行器數量等統計信息
    異常執行恢復機制,有時會遇到不可控情況,即執行機在執行後的執行結果因為網絡斷開等不可控因素導致不能發送給調度中心,此時能通過異常執行恢復機制臨時記錄,在下次執行機正常啟動時重試發送給調度中心
    調度手動觸發手動執行,特殊需求下,可能會要求調度可以手動執行,例如調度任務失敗之後可能需要手動執行一次調度來補償
    並行/串行策略,當定時時間遠大於任務執行時間時,可以使用並行策略,任務異步呼叫執行,提高任務調度精確度;當任務執行時間可能大於定時時間,卻需要任務按照某個定時規則定時調度時,可以使用串行策略,調度中心調度的當前任務的上一次觸發,如果沒有執行完,則當前執行機的下一次定時時間點時不會被觸發,當且僅當任務執行結束,以防止某些持續性定時任務的時間不確定性導致異步觸發時的資料混亂的情況發生,例如:某一任務的定時時間為10秒鐘,但是任務本身可能會出現執行超過10秒的情況,而超過時,如果出現兩個時間點的任務並行執行時會出現資料混亂的情況,此時就可以使用串行策略,確保當前執行機上一個任務未執行完,不會觸發新的執行
    支持調度接口資料監控,產生監控報表,便於觀測。

總結

   對於互聯網公司來說,時間就是金錢,效率決定一切。本系統在接入到8月初將近3個月的時間內,表現不凡,調度了約100萬次,給公司內部各服務實現任務調度提供了便利。




如果你對 Dubbo / Netty 等等原始碼與原理感興趣,歡迎加入我的知識星球一起交流。長按下方二維碼噢

目前在知識星球更新了《Dubbo 原始碼解析》目錄如下:

01. 除錯環境搭建
02. 專案結構一覽
03. 配置 Configuration
04. 核心流程一覽

05. 拓展機制 SPI

06. 執行緒池

07. 服務暴露 Export

08. 服務取用 Refer

09. 註冊中心 Registry

10. 動態編譯 Compile

11. 動態代理 Proxy

12. 服務呼叫 Invoke

13. 呼叫特性 

14. 過濾器 Filter

15. NIO 服務器

16. P2P 服務器

17. HTTP 服務器

18. 序列化 Serialization

19. 集群容錯 Cluster

20. 優雅停機

21. 日誌適配

22. 狀態檢查

23. 監控中心 Monitor

24. 管理中心 Admin

25. 運維命令 QOS

26. 鏈路追蹤 Tracing

… 一共 69+ 篇

目前在知識星球更新了《Netty 原始碼解析》目錄如下:

01. 除錯環境搭建
02. NIO 基礎
03. Netty 簡介
04. 啟動 Bootstrap

05. 事件輪詢 EventLoop

06. 通道管道 ChannelPipeline

07. 通道 Channel

08. 位元組緩衝區 ByteBuf

09. 通道處理器 ChannelHandler

10. 編解碼 Codec

11. 工具類 Util

… 一共 61+ 篇

目前在知識星球更新了《資料庫物體設計》目錄如下:


01. 商品模塊
02. 交易模塊
03. 營銷模塊
04. 公用模塊

… 一共 17+ 篇

原始碼不易↓↓↓

點贊支持老艿艿↓↓

赞(0)

分享創造快樂