quartz 報錯:java.lang.classNotFoundException


最近在做一個調度平台改造的項目,quartz在測試環境跑的是單機環境,生產上兩台服務器做集群。

測試環境是ok的,生產上線后報錯,一個類java.lang.classNotFoundException(注明:這個類被別人修改了名稱,現在使用的新名字)

第一次:失敗

從代碼上排除了對舊的job類的引用(配置文件和類都排除了)

推測是服務器緩存了該類。

嘗試:

  清除緩存,重啟服務器,仍然報上述錯誤。

第二次:失敗

   將生產上的配置拉到測試環境上,反復測試,重啟服務器時會自動清除緩存。

推測是quartz的那個類為全局變量,在生產上會做同步。

  嘗試:

   在測試環境上再次搭建一台調度服務器,從生產上將配置和執行全部拉到測試環境上,執行ok

  反復調試,仍然沒有發現同步的跡象。

  沒有重現生產上的異常,不敢上線了。

第三次:失敗

 那么這個舊的job類究竟從哪里調用的?找不到頭緒!會不會保存到數據庫吧?

 當時覺得這個想法很搞笑,從設計的角度上來說,quartz應該不允許將別的類引入到自己的體系吧。

 但也沒路可走,就查看數據庫,看看有沒有保存在數據庫中。你猜對了,它對原原本本的躺在數據庫的表中:

CREATE TABLE QRTZ_JOB_DETAILS(
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_VOLATILE VARCHAR(1) NOT NULL,
IS_STATEFUL VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (JOB_NAME,JOB_GROUP))
TYPE=InnoDB;

好吧! 查看該字段,發現確實是舊的類,被不是新的類。

那么為什么在測試環境中發現呢?

進入測試庫,也沒有發現舊的類,好吧。

第四次:成功

再次部署到生產上,還是報錯:類找不到。

確認問題處在數據庫中,我對quartz的表一張張的查找,仍然找不到這個記錄,那就從寫入庫開始入手,查了quartz的代碼,發現job_detail表中有個字段job_data,它的類型是blob,會不會存在這里呢?

確實,可以打開此blob查看,數據時放到這里了。

這個小心一些,再次檢查是否有別的blob字段存放舊的job類,發現在triggers表中也有個字段job_data,至此問題發現了。可怎么解決呢?blob類型的數據不能直接通過update來執行,畢竟要考慮到編碼的因素,拿就釜底抽薪,直接將類重構為以前的類。

從這次經歷來看,舊項目果然是坑,我就直愣愣的掉進去了。

結論:

計算機是個理性的東西,故一切皆有可能,即便是最不可能的事情也要去一一確認。在查找問題時最好想清楚所有發生故障的可能,然后一一排除,直到找到最終的問題。

對web開發來說,解決此類問題的一般思路如下:

1,從全局的角度來看,應用程序,緩存,數據庫是三大獨立模塊,這些部分都有可能發生異常,應該首先排查應用程序本身的異常(這個概率最大);其次是緩存(同步)模塊排查;最后是數據庫模塊排查。

2,全局確定好的前提下,細分上述的模塊,將可能出現的問題一一列出。

3,動手,驗證想法。對一個好的開發者來說,動手只是驗證的手段,思路才是最重要的。

 


免責聲明!

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



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