最近遇到一個奇怪的問題,有一個應用,分主從兩個節點,從節點啟動時會阻塞等待切換成主節點的通知,兩個節點每天晚上會停止(進程沒停,只是業務停止),第二天早上又會啟動,這個用了spring的@Scheduled去做,但實踐中發現第一天晚上正常按時停止,但第二天從節點沒按時停止,而住節點則正常停止,這導致了從節點切換成了住節點,然后奇怪的是從節點變成住節點啟動后馬上又按照schedule停止了。
經過調查最終發現,這是因為spring @Scheduled默認只有一個線程運行所有任務,第一天啟動是直接啟動應用時啟動的,並沒有通過schedule,到了一天晚上停止時才第一次用schedule,這一次正常運行,到了第二天從節點用schedule運行啟動,但這個任務被阻塞了,一直沒完成,這導致了到了第二天晚上從節點沒有線程去運行停止這個任務,等到從節點切換成住節點解除了阻塞狀態,把schedule的線程空出來了,所以馬上停止任務就可以運行了。
我把線程池大小調成2后就正常工作了。但一般來講線程池運行的任務最好是類型或大小都相似的,而且任務不應該有阻塞,這樣才能有效率以及避免錯誤。
