spring quartz 部分定時任務不執行問題定位修復方案

Quartz部分定時任務不執行問題分析過程及修復方案

背景:
2021年1月7號上線遷移需求之後,出現最爲明顯的 衆幫文件上傳 其他部分定時任務也不執行的情況 執行時間並沒有按照約定時間去執行

分析1 懷疑是代碼問題?

 對衆幫文件上傳定時任務代碼進行排查 並無發現編碼問題,並且對1月7號上的版本 和上一個版本進行代碼比對 並未發現對衆邦的代碼有所改動的地方

分析2 項目定時任務框架 spring quartz 內部任務存儲 調度問題?

  Quartz 是基於RAMJobStore調度中心去調度的,裏面有Job(任務),Trigger(觸發器)。

  通過對項目定時任務代碼的瞭解 及源碼的分析 得知:

項目啓動時 會把applicationContext-quartz.xml配置文件中的所有定時任務加載到jobDefinitions 這個隊列中,遍歷jobDefinitions 把每個定時任務的 job 和 Trigger獲取到,通過Quartz API 把定時任務添加到RAMJobStore, 經過對jobDetail的校驗 ,這裏主要是校驗name,group,jobClass 是否爲空,然後jobDetail的下次觸發時間是否合法 然後添加到RAMJobStore(JobWrapper, TriggerWrapper)中。
秉着這一邏輯思想
1月14號上線 項目重啓後 拉取項目 堆棧包heap1.hprof
使用jprofiler分析工具 打開heap1.hprof
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
如圖 找到RAMJobStore中的兩個存儲對象 發現job 和 trigger中存儲的數量是一致的,於是我打算點對點的排查 由於生產最爲明顯的是衆幫文件上傳定時任務不執行 所以我從這76任務中,找到衆幫文件上傳的wrapper 看看是不是有什麼問題。在這裏插入圖片描述
如圖可以看出 衆幫文件上傳的定時任務 從開始執行時間,下次觸發時間,是否有配套的監聽器 都是正常的 ,可就是不執行,於是我開始quartz調度的過程,如何調度的執行的。
幾經翻查 發現quertz 定時任務在調度時,都需要初始化一個線程池SimpleThreadPool 而這個線程池大小默認是10,而quertz任務觸發調度的原則是:
1、線程池資源獲取等待定時任務過期作廢機制。
2、Quartz框架的定時任務執行是絕對時間觸發的,所以存在“過期不候”的現象。










所以開始懷疑是項目定時任務過多87個 並且大部分定時任務都是 10秒 ,20秒,30秒 1分鐘執行一次 過於密集

分析3 quartz 調度初始化沒有問題 定時任務多,且時間密集導致?

爲了復現和生產一樣的情況 衆幫及其他部分定時任務不執行的情況,由於測試環境基本沒有數據,所以每個定時任務執行的非常快,所以不存在生產的情況,所以我把代碼中每個定時任務 讓他們執行時,都線程等待60秒,並且做了一個定時任務計數器。
“fpcCallBack”:205,
“alipayPromoteDataAndRule”:1657,
“bdTransactionCallBack”:680,
“networkVerifyDataAndRule”:5,
“processDataAndRule”:976,
“paphLoanDataAndRule”:203,
“fplCallBack”:124,
“jdDataAndRule”:828,
“paphDataAndRule”:312,
“callBack”:511,
“fpShareLoanPeople”:1260,
“fpcDataAndRule”:1282,
“wsdMigrateCreditAckDate”:9,
“zhongbangFileUp2View”:“1”,
“sendTxnJob”:“1”,
“AliPayBigTextAnalysis”:393,
“pplDataAndRule”:33,
“sendTxnBdCreditMigrate”:18,
“blackList”:46,
“sendTxnJDLoan”:15,
“creditCallBack”:1312,
“fileSyncDataAndRule”:1529,
“ppcDataAndRule”:127,
“jLFSCallBack”:62,
“qlLoanDataAndRule”:2,
“OpenAccountNetCheck”:54,
“zbCallBack”:3,
“yjSendTxnLoan”:5,
“gjjCallBack”:101,
“ppdDataAndRule”:82,
“alipayDataAndRule”:1687,
“jfDataAndRule”:506,
“jfCallBack”:17,
“qlLoanCallBack”:2,
“bdCreditDataAndRule”:4966,
“alipayHBDataAndRule”:1673,
“fileSyncCallBack”:3123,
“youXLoanDataAndRule”:6,
“pplCallBack”:4,
“bdCreditCallBack”:794,
“wsdConfirmDataAndRule”:12,
“bdAdjustLimitMigrate”:3045,
“sendSoapJob”:1102,
“OdMonitor”:1321,
“estDateSourceMonitor”:25,
“qianLLCallBack”:4,
“yxCallBack”:“1”,
“jLFSDataAndRule”:605,
“zbDataAndRule”:2,
“cxcDataAndRule”:535,
“bdTransactionDataAndRule”:3224,
“bdAdjustmentCallBack”:1020,
“fileUpload”:678,
“bdCreditMigrate”:2043,
“yxLoanDataAndRule”:6,
“sendTxnLoan”:11,
“ppcCallBack”:9,
“wsdDataAndRule”:10,
“dfCallBack”:477,
“cxlDataAndRule”:475,
“gjjDataAndRule”:725,
“qianLLoanDataAndRule”:519,
“qlCallBack”:“1”,
“fileDownloadAndUpBD”:386,
“tszCallBack”:“1”,
“tszDataAndRule”:“1”,
“yxDataAndRule”:6,
“bdAdjustmentDataAndRule”:6760,
“yjDataAndRule”:8,
“jdCallBack”:1153,
“bdTransactionMigrate”:1913,
“wsdMigrateCreditDate”:9,
“yjFileSyncDataAndRule”:8,
“fplDataAndRule”:1308









































































從計數器打印結果可以看出
在測試環境執行了15小時左右 果然出現了和生產一樣的情況
一共87個定時任務 執行了73個有19個未執行 已執行的存在執行次數爲個位數的情況

所以我認定quartz定時任務執行存在線程瓶頸 與此我發現爲什麼衆幫的文件上傳一次執行的機會都不能搶到嗎?想必小夥伴們也會有這種猜疑 就算觸發時間相同情況下 可觸發的數量有限 難道衆邦一次都搶不到執行線程嗎?

於是 又一頓的百度 博客 終於找到了對應的解釋
默認情況是觸發時間先後順序排列,觸發時間比較前的先執行任務,但如果一個或多個任務同時在相同時間觸發下,觸發器設置優先級越高越先執行。如果優先級相同,則跟任務的存儲方式有關,RAMJobStore時與TriggerKey排序有關,即按觸發器名的字母序;如果是JdbcStore則跟數據庫查詢的默認排序有關了。Trigger優先級默認爲5,數值越大優先級越高

這會大家應該明白了吧 衆邦的定時任務名稱叫做 zhongbangFileUp2ViewJob 所以 在相同觸發條件下 並且執行數量有限的情況下,他被淘汰了

**

問題解決:

那麼此時留下的問題就是 解決 quartz執行線程數量太少10個的問題
我們要做的就是 增加quartz 執行線程數量
由於本項目 quartz 的框架版本過低1.5.2 無法通過quartz.properties
進行聲明線程數量 這裏我就不想吐槽了 試了很多種辦法不行 ,而且版本調整到2.0.0以上後 OPS 封裝的quarzt代碼全部報錯 版本完全不兼容。
於是我們在applicationContext-quartz.xml中
在這裏插入圖片描述
在SchedulerFactoryBean中對quartz.properties進行復寫 並且改變線程數量爲100,以及Trigger檢查器 默認每次只Acquire一個Trigger。





丟到測試環境測試 定時任務計數器打印結果如下:
“bdCreditDataAndRule”:128,
“fpShareLoanPeople”:14,
“gjjCallBack”:14,
“youXLoanDataAndRule”:16,
“jdCallBack”:15,
“jfCallBack”:31,
“bdAdjustLimitMigrate”:30,
“sendTxnJDLoan”:32,
“pplDataAndRule”:15,
“estDateSourceMonitor”:“1”,
“fplDataAndRule”:11,
“wsdMigrateCreditDate”:9,
“creditCallBack”:7,
“paphDataAndRule”:10,
“tszDataAndRule”:12,
“ppdDataAndRule”:51,
“wsdMigrateCreditAckDate”:19,
“dfCallBack”:10,
“yxLoanDataAndRule”:43,
“zhongbangFileUp2View”:2,
“qianLLoanDataAndRule”:11,
“fpcDataAndRule”:12,
“callBack”:9,
“paphLoanDataAndRule”:11,
“pplCallBack”:11,
“blackList”:2,
“yjSendTxnLoan”:39,
“ppcDataAndRule”:20,
“cxlDataAndRule”:10,
“yxLoanCallBack”:14,
“gjjDataAndRule”:23,
“processDataAndRule”:19,
“sendTxnLoan”:37,
“ppcCallBack”:15,
“alipayPromoteDataAndRule”:8,
“qlLoanCallBack”:8,
“qlCallBack”:6,
“bdTransactionDataAndRule”:129,
“qlDataAndRule”:8,
“fileSyncCallBack”:156,
“plagueMonitor”:2,
“yjFileSyncDataAndRule”:49,
“fplCallBack”:10,
“bdAdjustmentCallBack”:19,
“bdAdjustmentDataAndRule”:149,
“sendTxnBdCreditMigrate”:39,
“bdCreditCallBack”:14,“fpcCallBack”:9,
“bdTransactionMigrate”:35,
“yjDataAndRule”:39,
“cxcDataAndRule”:14,
“bdTransactionCallBack”:24,
“sendSoapJob”:22,
“fileDownloadAndUpBD”:24,
“alipayDataAndRule”:8,
“OpenAccountNetCheck”:3,
“fileUpload”:7,
“AliPayBigTextAnalysis”:11,
“qlLoanDataAndRule”:14,
“jfDataAndRule”:10,
“qianLLCallBack”:24,
“bdCreditMigrate”:35,
“alipayHBDataAndRule”:13,
“wsdDataAndRule”:38,
“jdDataAndRule”:15,
“yxDataAndRule”:8,
“sendTxnJob”:19,
“wsdConfirmDataAndRule”:37,
“yxCallBack”:10,
“OdMonitor”:14,
“fileSyncDataAndRule”:36,
“zbCallBack”:15,
“tszCallBack”:11,
jLFSDataAndRule":13,
“jLFSCallBack”:9,
“zbDataAndRule”:39










































































從結果中可以看出 每次定時任務都執行了,並且執行的次數都比較均勻,不像一開始 有的執行幾千次,有的執行幾十次,受線程執行數 已經定時任務首字木影響較大。 而且從結果中可以看出 衆幫的數據處理執行了39次 衆邦的文件上傳 每10分鐘執行一次 每次輪到執行的執行時,都執行了,不存在拿不到執行線程的情況

quartz定時任務使用結論

1、線程池資源獲取等待定時任務過期作廢機制。
2、Quartz框架的定時任務執行是絕對時間觸發的,所以存在“過期不候”的現象。
3、在使用Quartzs框架時,一定要預先計算好triggers數量與線程池大小的匹配程度,資源一定要夠,或者任務執行密度不能太大,否則等到線程任務釋放完,trigger早已過期,就無法按預期時間觸發了。
4、在進行業務代碼開發過程中 儘量一個定時任務中處理多種業務代碼,做異步線程處理,對定時任務進行歸類 抽取
5.根據業務情況 不要一上來就增加定時任務,靠定時任務處理問題



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章