spring定時任務ThreadPoolTaskScheduler使用注意事項之線程池大小


背景

最近小伙伴解決了一個工單,描述為“手工推送案件無法推,提示token失效”,當前工單狀態為待關閉,解決方案為“東軟接口不穩定造成的,東軟的接口恢復正常后,問題解決”,然后找現場讓他們關閉工單,現場反饋:今天現場又出現相同的問題了!!!依然是token失效,工單關不了了。

過程

確認問題應用及版本

讓對方把錯誤截圖發了一下,發現好像不是卷宗自己的應用,跟卷宗團隊小伙伴確認了一下,這是個定制的小工具。要到源碼看了下,版本很干凈,也不需要跟現場要版本號了,直接看當前代碼即可。

問題初次定位

token失效有可能是服務器與客戶端時差較大導致的,讓現場核實了一下,就差幾秒,不是這個原因。
讓現場復現一下問題,並跟代碼,發現所有請求東軟接口的地方都需要在請求頭傳遞token信息,而這個token是單例的,初次使用時會實例化。

現在既然找到token賦值的位置,且是單例的,現在又失效了,重啟一下一定能解決,讓現場重啟

重啟后確實解決了,從而得出結論“咱們只有在啟動的時候申請了一次token,以后就再也沒申請過,東軟設置了token超時自動過期”,看看能不能讓東軟那邊設置token永不過期

問題再次定位

但是!人家東軟說token有效期是固定的兩小時,且出問題的應用之前已經平穩運行好幾天了。

基於目前的結論來看,每2個小時就需要重啟一次應用才會避免token失效呀,現在的現象明顯不是這樣,怎么肥事?
繼續找代碼吧,看看都哪兒操作到token這個屬性了,然后就找到了一個定時任務!

原來人家寫了每半小時刷新一次token,而半個小時是小於東軟的2小時的,所以理論上不會出現token失效的問題,那下一步的方向是哪兒呢?
定時任務嘛,看任務是否成功執行了就可以,反正他原來也有日志。
搜索了一遍之前的日志,沒找到成功刷新的日志,這是怎么肥事?歷史日志看不出來,咱們就看新日志吧。

到時間后為什么定時任務沒執行?來,看代碼,看日志!
代碼里之前已經看到了,用的是spring提供的ThreadPoolTaskScheduler創建的定時器,沒啥問題,看日志吧。

任務雖然執行成功了,但是日志有點兒怪呀,為什么刷新token的線程threadPoolTaskScheduler-1還被其他實例使用了?又不是主線程,他們應該是分別使用自己的才對呀,去SyncDataService看看。

哦哦,原來他們用的是同一個定時線程池的實例,擴散的看一下,原來有4個定時任務用的同一個實例。

那難道是他們在排隊執行嗎?去看一下ThreadPoolTaskScheduler的實現,網上說默認他只有一個工作線程,如果存在多個任務被觸發時,會等第一個任務執行完畢才會執行下一個任務,看了下源碼確實是這樣。

回過頭來看看日志是否可以佐證我們的猜想,11點41項目啟動成功,定時任務實例化成功。

12點 SyncMaterials 任務開始執行(直接搜 threadPoolTaskScheduler-1 即可,因為默認線程大小是1,所以所有任務的工作線程名稱都是他)

12點26 SyncMaterials 任務執行完畢,開始執行 SyncDataService

12點35 SyncDataService 任務執行完畢,開始執行 ScheduleService

再看看之前幾天的日志,佐證一下猜想,可以看到確實是差不多每半小時執行一次。

解決方案

1、手工設置ThreadPoolTaskScheduler線程池大小,使其與定時任務數保持一致,每個任務用單獨的工作線程,互不干擾(定時任務太多時其實存在資源浪費,每個任務都會有一個工作線程單獨執行,間隔時間長且執行時間短的任務會始終占用着這個線程資源)
2、不要用spring自帶的ThreadPoolTaskScheduler了,自己使用ScheduledExecutorService實現任務調度
3、找其他更合適的框架實現定時任務調度

結語

勁酒雖好,可不要貪杯哦!!!
腦子里為什么突然就有畫面了???我還年輕,我一定不知道這些老年人才知道的廣告詞!!!
說正經的:不知道自己不知道->知道自己不知道->不知道自己知道->知道自己知道,咱們要努力做到最后面的那種境界。
套用到代碼的世界就是,小白時期好多東西都不知道,定時任務都不知道是什么,只知道每天做自己已知的事兒,不就是增刪改查嘛,有什么難的,大家都這樣干,我也這樣干;
后來聽人家說了,有個定時任務的概念,spring可以實現這個功能,可以怎么用,自己遇到類似需求的時候,直接就去網上找關鍵字spring 定時任務,管他天高路遠,管他山高水長,用就完了,干就是了;
再后來掉的坑多了,就知道看源碼了,知道去看spring定時任務的原理了,后續工作中也知道再用spring定時任務的時候需要避免采什么坑,如何避免了,一陣沾沾自喜;
但后來被別人問的多了,或者自己開竅了,就知道除了spring自帶了定時任務執行器,還有很多其他的方式可以實現相同的功能,他們各自的適用場景及優劣勢是什么,自己當前的業務場景更適合用哪一種?開始做技術選型及預研了,這才是我們要追求的目標。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM