該片文章主要是記錄下最近關于任務管理的一些想法吧,項目中使用的任務多了,有不少缺點,就想實現一個更好的,但目前只是有點思路,至于后路如何,估計會流產吧。
目前項目中的任務實現方式
任務分類:
- 非定時任務:需要實時判斷是否有待執行任務,有則立即執行。例如發送驗證碼,當檢查到有待發送時執行發送操作。
- 定時任務:在某個固定時間或按某個固定周期/間隔執行的任務。例如同步歷史數據,每天23:59分執行。
針對非定時任務實現手段:
- 編寫單獨的main方法,創建shell腳本執行。
- 隨項目啟動,項目啟動時調用某個init方法。
- 如果是并行任務,則創建多個進程。為了便于擴展,總進程數和當前分配的進程號等參數動態傳遞給main方法,在方法里面通過取模等實現不同進程間數據隔離。
目前我所在項目中普遍采用創建shell腳本執行。
缺點:
- 每編寫一個任務,就需要編寫shell,導致服務器上一堆.sh腳本,增加維護成本,每次上線都需要重啟。
- 針對多進程任務,一般進程號等參數是編寫在shell腳本中傳遞給main方法的。如果現在增加一個進程處理,由于要修改總進程數和指定當前進程的處理進程號,需要修改shell腳本要將之前的進程全部重啟,影響很大;當然也可以將總進程號配置在數據庫中,但是修改數據庫的風險也不小。
針對定時任務實現手段:
- 使用Timer或scheduleThreadExcutor等原生java編寫
- 使用Quarz等第三方框架。
我所在項目是使用的基于Quarz自己二次開發的框架,相比Quarz的優點是將任務的配置信息存放到數據庫和緩存中了,如果需要修改某個數據庫的執行時間,只需要修改數據庫相關信息,然后刷新緩存就可以了,無需重啟服務器。
但該方法也有缺點,如果是直接使用的配置文件,服務器還不支持熱部署,那就比較麻煩了,每次修改都需要重啟項目;即便是基于數據庫的,修改數據庫的風險也很大,且不說是否有權利修改等。
總體缺點:
- 修改配置不方便。
- 并行任務,擴展不方便。
- 管理困難,一堆sh腳本,維護成本高。
- 處理結果不透明,發生異常時,運維人員無法立刻知曉。
- 沒有統計信息,無法具體知曉某個服務器或任務等執行了多少次,失敗率是多少,成功率是多少。
- 針對定時任務,無法快速的觸發一次。
- 無操作記錄信息。
針對以上缺點,想開發一個方便管理,易于使用的任務處理框架,意在解決上述缺點。
基于zk的任務處理框架
使用該框架,對開發人員來說可能不會有什么顯著影響,之前該寫的業務邏輯還是需要寫的,如果非要說有什么影響,那就是你可以直接寫對應的業務代碼,無需關心任務的具體處理流程。該框架主要是減輕運維人員的工作量,提供了很多直觀的WEB功能,增加靈活性和擴展新。
理想情況:
開發人員下載客戶端Jar包,實現相應接口,開始編寫具體的業務邏輯代碼,僅此而已,無需再關系任務的具體處理細節。運維人員登陸WEB端界面,設置某個Task的執行計劃。OK,至此該Task就可以工作了。
WEB端功能:
- 創建,刪除和修改Task。
- 創建Task時:
2.1. 允許設置任務的執行計劃,定時,固定周期,固定間隔等。
2.2. 允許設置任務處理計劃,并行處理,單獨處理等。
2.3. 允許指定具體服務器執行。
2.4. 允許單次觸發。
2.5. 允許設置發生異常時的通知方式,短信,釘釘等。 - 統計功能,展示某個Task對應的服務器的執行情況,包括:執行次數,成功率等信息。
- 監控功能,上次執行情況。
- 操作記錄,每一次操作都需要記錄日志。
- 安全。功能授權等信息。
客戶端JAR功能
- 提供相應的接口,供開發人員使用。
- 向ZK注冊TASK。
- 針對并發任務,當新增服務器時,自動感知并更改該任務的服務集的入參,例如總進程數,每個服務分配的進程號等信息。
- 獲取可用服務集,針對并發處理任務,分發出去。
原理:
主要是基于ZK提供的通知機制,在某個節點設置監視點,由服務端主動通知該節點下的所有客戶端。