常見分佈式任務框架在高併發下的性能分析
前言
當大量定時任務需要在同一時刻運行時,任務平臺的任務延遲會顯著增大,這是因爲任務平臺負載過高,導致任務運行延遲增大。本文對常見的分佈式框架進行壓力測試以及性能分析,從源碼層面找到性能差異的原因,同時希望通過測試與分析,可以開發出在高併發場景下,實現更低延遲的任務平臺。
壓力測試
測試方法
每個任務平臺都創建 5000 個 cron 表達式(*/30 * * * * ?)
任務,這些任務會在 0 秒和 30 秒時,同時運行。我們通過觀察任務在每秒的執行情況,得到它們的調度延遲,比如任務在 0 或 30 秒處運行則它們的延遲爲 0 秒,如果在 1 秒和 31 時運行,則它們的延遲爲 1 秒。爲方便畫圖,我們只統計 5s 延遲以內的任務。延遲越低,執行的任務數量越多,則表示框架性能越佳。
測試對象
-
•
devops schedule
: 騰訊藍盾團隊自研分佈式任務框架,目標是實現低延遲,高併發,支持海量任務的分佈式任務框架,測試版本爲開發版本,還未正式發佈。 -
•
quartz
: Java 領域知名分佈式任務框架,應用最廣泛,測試版本是 v2.3.2。 -
•
xxl-job
: 國產分佈式任務框架,在 github 上擁有 27k 多個 star,測試版本是 2.4.1。
三者都是採用單機部署模式。
測試結果
圖中只展示延遲在 5s 內任務數
從圖中我們可以看出 devops schedule 框架完成的任務數量遠遠超過另外兩款框架。
這是爲什麼呢?下面我們將從它們的源碼處進行分析
源碼分析
最令人好奇的是 xxl-job,爲什麼它連一個任務都沒有完成?所以我們先從它開始分析
xxl-job 分析
查看日誌可以發現所有的任務都 misfire,從源碼中找到 msifire 的實現。這裏的 PRE_READ_MS 爲 5000,也就是說任務觸發晚於 5s 即產生 misfire(所有測試用例中 misfire 策略爲 DO NOTHING,也就是直接錯過任務)。
所以我們可以知道 xxl job 在調度一輪的任務中耗時超過 5s。接下來,我們在源碼關鍵位置進行日誌埋點,發現以下這段代碼耗時長達 40 多 s。
這裏很容易看出問題,任務越多,更新的耗時就越久,調度程序本身就耗時就更久,自然就會發生錯過任務的情況,這裏明顯設計的不太合理。quartz 相對好些,不經好奇,它又是怎麼處理的?
quartz 分析
分析 xxl-job 我們得知,在調度任務過多時,更新大量任務會導致調度程序本身耗時過長,以至於任務延遲增大,甚至錯過時間執行。
從測試結果上看,quartz 沒有錯過所有任務,且 quartz 和 xxl-job 都是使用的 mysql 數據庫,所以在實現上 quartz 肯定有它的特別之處,以避免上述問題。
查看源碼,我們可以看到,quartz 在查詢待觸發的任務時,同時使用了時間窗口與數量限制,所以它一次性不會處理過多任務。
xxl job 也有時間和數量限制,但是數量值只是一個提前預估的固定值。實際運行時,這個預估值還是會遠大於系統的運行能力,這時將會導致調度任務過多,系統負載過大。
xxl-job 查詢任務
xxl-job 任務數量
devops schedule 的性能明顯超過上面兩者,這背後的原因又是什麼呢?
devops schedule 分析
上面的一個核心問題是,如何保證調度任務數量可控,以避免系統負載過高,任務延遲增大,甚至錯過執行。
三者都有時間窗口限制,主要看看它們在數量上是怎麼控制的。
- xxl job
- 預估一個數量,這與實際運行能力可能會有很大的差異,導致控制效果不佳。
- quartz
- 取活躍線程和人工設置批處理數量兩者的最小值。這裏有活躍線程數,可以動態調整任務數量,效果比較不錯。
- devops schedule
- 設計時,源自 tcp 擁塞控制的靈感,我設計了基於系統負載能力,即任務延遲大小,動態調整任務數量。當任務延遲高於閾值時,將降低任務數量,反之則加大任務數量。採用 tcp reno 算法,以快速讓系統達到預期穩定值。
實際上,上面效果巨大的差異並非來自數量調控,主要是 devops schedule 採用了非關係數據庫 mongodb,在同樣更新 5000 條任務記錄下,mysql 需要 40 多 s,而 mongodb 只需要 10s.
另外我在線程池上也做了優化,普通 jdk 線程池是單隊列的,所以存在多線程搶佔鎖。我設計了新的線程池,每個線程都有自己的隊列,避免了多線程搶佔鎖的問題,這裏像 netty,jetty 這些高性能框架,也是這麼設計的。
結論
在任務高併發的情況下,devops schedule 的性能遠超過其他兩個框架,這主要是因爲 devops schedule 框架是個全新設計的框架,可以集百家之所長,具備後發優勢。
但是 devops schedule 是新的分佈式任務框架,所以它的功能性有所欠缺,現在主要的設計目標是支持海量任務調度,同時高併發的情況下可以做到更低延遲。
結束語
後面有時間會再寫一篇關於分佈式任務框架,架構分析的文章,這裏只是測試了它們的單機版本,單機能力總是有限,肯定需要集羣化來實現更大的任務調度吞吐。架構設計的好壞將直接關係它們的集羣性能的好壞,比如是否支持水平擴展等,瞭解它們在架構層面的優缺點,以在需要時進行正確的技術選型。
框架地址
[1]
devops schedule: https://github.com/bkdevops-projects/devops-framework.git
[2]
quartz: https://github.com/quartz-scheduler/quartz.git
[3]
xxl-job: https://github.com/xuxueli/xxl-job.git
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/DsyYaCxEpLpdJkitBqWDLQ