常見分佈式任務框架在高併發下的性能分析

前言

當大量定時任務需要在同一時刻運行時,任務平臺的任務延遲會顯著增大,這是因爲任務平臺負載過高,導致任務運行延遲增大。本文對常見的分佈式框架進行壓力測試以及性能分析,從源碼層面找到性能差異的原因,同時希望通過測試與分析,可以開發出在高併發場景下,實現更低延遲的任務平臺。

壓力測試

測試方法

每個任務平臺都創建 5000 個 cron 表達式(*/30 * * * * ?)任務,這些任務會在 0 秒和 30 秒時,同時運行。我們通過觀察任務在每秒的執行情況,得到它們的調度延遲,比如任務在 0 或 30 秒處運行則它們的延遲爲 0 秒,如果在 1 秒和 31 時運行,則它們的延遲爲 1 秒。爲方便畫圖,我們只統計 5s 延遲以內的任務。延遲越低,執行的任務數量越多,則表示框架性能越佳。

測試對象

三者都是採用單機部署模式。

測試結果

圖中只展示延遲在 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 分析

上面的一個核心問題是,如何保證調度任務數量可控,以避免系統負載過高,任務延遲增大,甚至錯過執行。

三者都有時間窗口限制,主要看看它們在數量上是怎麼控制的。

  1.    預估一個數量,這與實際運行能力可能會有很大的差異,導致控制效果不佳。
  1.     取活躍線程和人工設置批處理數量兩者的最小值。這裏有活躍線程數,可以動態調整任務數量,效果比較不錯。
  1.    設計時,源自 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