SpringBoot中DataSource配置@ConfigurationProperties注解的坑

背景

今年負責一個特別緊急的項目,從需求溝通到應用上線只有一個月的時間,四月中旬開始具體溝通項目需求并準備資源,五月中旬要完成第一次上線。這次不聊整個項目的開展過程,而是說一下通過一個月艱苦卓絕的奮斗,順利完成了需求溝通、分析、設計、開發、測試、驗收,上線前也準備了詳盡的上線序列并一一清點了,但上線時應用啟動時出現的一個異常的排查過程。

現象

測試環境驗證通過后,將鏡像推送給運維部署到生產環境,應用啟動時報如下錯誤

[ERROR] [DbSessionContextPlugin.java:] 測試數據庫連接失敗(Test DB Connection Fail)[driver:oracle.jdbc.driver.OracleDriver,url:store:xxxx.store:xxxx,user:uuuuuu]
java.sql.SQLException: No suitable driver found for store:xxxx.store:xxxx
        at java.sql.DriverManager.getConnection(DriverManager.java:689)
        at java.sql.DriverManager.getConnection(DriverManager.java:247)
        at com.sinolife.sf.framework.dbcontext.DbSessionContextPlugin.testConnectionValidate(DbSessionContextPlugin.java:427)
        at com.sinolife.sf.framework.dbcontext.DbSessionContextPlugin.postProcessAfterInitialization(DbSessionContextPlugin.java:61)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:437)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:579)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
        at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$146/1684106402.getObject(Unknown Source)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
......

差異

測試環境與生產環境之間的差異主要有兩個方面

  • 數據庫連接串的配置方式
測試環境的配置方式
jdbc.user=system
jdbc.password=oracle
jdbc.jdbcUrl=jdbc:oracle:thin:@ip:port:uid
生產環境的配置方式
jdbc.user=tmsopr
jdbc.jdbcUrl=store:xxxx.store:xxxx

生產的配置方式是將連接串及秘鑰信息加密保存到指定路徑下的xxxx.store文件,需要這些信息時再去store文件中讀取,目的主要是指定路徑權限和加密方式可以保證敏感信息的安全,防范攻擊。

  • 數據庫版本差異
    測試環境數據庫是11G,而生產環境數據庫是19c。公司其他應用使用的11G,11G官方支持周期到2018年就結束了,于是公司開始嘗試使用oracle 19c的版本,而我們的應用有幸成為了第一個嘗試者。

分析 - 數據庫版本差異

根據異常日志信息java.sql.SQLException: No suitable driver found for第一反應是oracle升級了,但是ojdbc驅動沒有升級,有可能是驅動版本老舊導致的問題。解決方法有兩個:升級OJDBC驅動版本;回退oracle數據庫版本。

  • 升級OJDBC驅動版本
    由于項目中間使用了兩個個數據源,應用的數據庫是19c的版本,而另一個數據源數據庫的版本是11c,如果升級OJDBC驅動的版本,有可能會影響另一個數據源。另外,MAVEN中對OJDBC的依賴較多,調整影響面大,而且需要架構組支持,有可能會出現反復調整并測試驗證的情況。為了盡快解決問題讓應用部署上線,放棄升級OJDBC驅動的方案。


    ojdbc的依賴關系
  • 回退oracle數據庫版本
    選定了方案之后,第一時間與運維溝通好后,運維開始協助回退oracle數據庫的版本。運維一陣犀利的操作過后(導出、刪除19c、創建11g、導入),數據庫回退成11c的版本。
    滿懷希望的通知部署人員重新部署應用,然而令人絕望的是,依然是原來的錯誤,一模一樣。
    說明: 此處優先選擇這個方案另一個重要的原因是測試環境oracle是11g,應用可以正常啟動,至于為什么測試和生產不一致,后面會提及。

分析 - 數據庫連接串的配置方式

數據庫回退沒解決掉問題,只能將矛頭指向數據庫連接串的配置方式上了。將生成環境的連接串配置方式調整為和測試環境一致,jdbc.jdbcUrljdbc.password直接在配置文件中寫死。調整后重新打包鏡像并推送運維部署。
應用居然成功啟動了!
開始懷疑是不是store文件的格式和解析是否有問題?但是這個是通用的模塊,已經使用很多年了。為了消除疑惑,改回從store文件讀取jdbc.jdbcUrljdbc.password配置,增加日志,重新部署啟動還是和原來一樣報錯。檢查輸出日志,參數都正常解析并獲取到了。那究竟為什么在properties文件中配置就可以,而在store文件中配置就報錯了呢?
數據源的配置很常規,很簡單,如下:

    @Bean(name = "dataSource")
    @Primary
    @ConfigurationProperties(prefix = "jdbc")
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = DataSourceBuilder.create().type(ComboPooledDataSource.class).build();

        String jdbcUrl                 = context.getEnvironment().getProperty("jdbc.jdbcUrl");
        String user                    = context.getEnvironment().getProperty("jdbc.user");
        String driverClass             = context.getEnvironment().getProperty("jdbc.driverClass");
        ......

        // 從store文件中解析并讀取jdbcUrl和password
        String[] jdbcUrlAndPassword = DbParamterResolverUtil.resolveJdbcUrlAndPassword(jdbcUrl, user, null);
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl(jdbcUrlAndPassword[0]);
        dataSource.setUser(user);
        dataSource.setPassword(jdbcUrlAndPassword[1]);
        ......

        return dataSource;
    }

通過再次仔細分析異常日志,將焦點放在了@ConfigurationProperties(prefix = "jdbc")這個注解上,

......// 原理待完善

@ConfigurationProperties(prefix = "jdbc")注解去掉,重新部署,一切正常。

思考

  • 知其然,知其所以然
    作為一個程序員不求甚解是要不得的,應該在熟練使用工具的同時,多了解其背景和原理,這樣才不會濫用,遇到問題才能快速準確的定位。

As a programmer, I hate to use things I don’t understand.

  • 溝通
    應該積極主動的溝通,不應該回避溝通,避免出現信息孤島。
    其實運維的同事在開發環境部署了一套19c,但是并沒有通知我們。由于項目周期短,時間太緊張了,開發人員直接在測試環境開發,已期望提高部署和用戶驗證的效率。從而導致了很多不必要的操作。
  • 規范
    我們有開發、測試、生產三個環境,考慮到項目時間緊張,期望最大化提高效率,只維護了測試環境,直接忽略了開發環境。這樣不規范的操作導致了一系列的問題,環境問題,配置問題,開發頻繁部署,導致用戶測試體驗極差等等。
    開發、測試、生產環境應該保持一致,都應該部署19c的數據庫,但是不知道什么原因運維再開發部署了19c、測試部署了11g、生產部署了19c。環境不一致增加了問題分析的很多不必要的復雜度。
    引入更新或一項新技術的時候,應該先做好充足的知識儲備和測試環境驗證(最好由架構組先嘗試、總結、然后培訓推廣),而不是盲目的嘗試,評估的時候應該更謹慎。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容