一.前言
這個錯誤很詭異, 困擾了我一週左右, 很苦惱,很煩躁, 如鯁在喉,不吃不快啊! 當然忙別的時候也會忘掉這個苦惱和煩躁. 因爲雖然報錯了,但是不影響程序的任何使用, 這就奇怪了, 如果非要說影響, 那就是"佔着茅坑不拉屎", 一直在服務器控制檯霸屏. 如果你也有類似的問題, 或者對着問題感興趣, 那請繼續看下去, 精彩的在後面.
二.報錯信息
Exception in thread "vertx-jdbc-service-get-connection-thread" java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
at com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:975)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109)
at io.vertx.ext.jdbc.impl.JDBCClientImpl.lambda$getConnection$3(JDBCClientImpl.java:197)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
這個報錯信息, 以50.36秒左右的頻率打印一次, 別問我這個時間從哪裏來的, 問了我也不會告訴你我是用手機計時器統計出來的. 從報錯信息可以看出, vertx的一個線程獲取connection連接失敗, 因爲dataSourceClassName or jdbcUrl沒有配置. 主要就是這個意思.
三.問題分析
public static DataSource getHikariDataSource(JsonObject cofig) {
_LOG.info("getHikariDataSource,config:{}",cofig.toString());
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(cofig.getString("url"));
ds.setUsername(cofig.getString("username"));
ds.setPassword(cofig.getString("password"));
ds.setConnectionTestQuery(cofig.getString("connectionTestQuery", "SELECT 1"));
ds.setConnectionTimeout(cofig.getLong("connectionTimeout", 30000L));
ds.setIdleTimeout(cofig.getLong("idleTimeout", 600000L));
ds.setMaxLifetime(cofig.getLong("maxLifetime", 1800000L));
ds.setMaximumPoolSize(cofig.getInteger("maximumPoolSize", 10));
ds.setMinimumIdle(cofig.getInteger("minimumIdle", 10));
//ds.setLeakDetectionThreshold(30000); //connection泄漏檢測
return ds;
}
1.debug或者打印日誌, 發現connection 裏面都是有值的
2.程序在本地運行沒有任何問題
3.程序在Linux服務器上運行也不影響任何接口的CRUD操作, 就是單純的報錯,讓我們回顧一下這個錯誤信息
Exception in thread "vertx-jdbc-service-get-connection-thread" java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
綜上所述: 在我撫摸了三個小時的劉海後, 我冷靜並且精準地分析出了, 1.肯定不是配置dataSorce or jdbcUrl的問題, 因爲如果配置出現問題, 接口根本就不能用. 2. 那就是你在設置數據源,設置數據庫參數之前就調用連接了,正常人應該不會這樣, 經過驗證,我確實是個正常人. 3.那就是有人欺騙了你, 你看到的並不是真的. 當我正要在幻境中遨遊的時候, 旁邊的老王, 一句話把我帶進了現實,"你個xx,摸夠了沒有, 就剩下三根劉海, 還摸." 是的,這個時候, 我就想有可能看到的報錯信息,是別的進程輸出的, 按照這個思路一路走下去, 最終發現了終極答案.
四.解決方法
1.日誌全部都輸出在 nohup.out中, 那就來看一看, 這個nohup.out都有誰在用, 在nohup.out所在的目錄下,輸入下面指令
指令和結果:
有三個進程在調用這個pid, 看到這個結果, 非常高興, 證明方向應該是正確的.
2.查看自己程序的進程id是多少
指令和結果:
這就可以得出結論: 9392 和 9393 也在往nohup.out裏面輸出日誌
3.來看看4324和9392和9393是什麼進程
通過對比,相信機智的你, 應該能發現問題, 4324是正在運行的程序, 9392是腳本文件的一個程序, 9323可能是某次沒有kill成功,然後一直在後臺運行,往nohup.out輸出日誌,就出現了那種"輸出着異常日誌, 但是不影響任何使用"的詭異現象. 我每次運行程序, 都是先kill -9 pid, 然後 nohup sh start.sh & . 如果有知道出現這種問題的具體原因,並且以後可以更好的規避的大神, 歡迎留言,不吝賜教.
4.將這三個進程殺掉, 然後重新啓動自己的程序
kill -9 4324
kill -9 9392
kill -9 9393
nohup sh start.sh &
OK, 完美運行!
五.總結
開發過程中,會遇到各種各樣的問題, 調整心態, bug虐我千百遍, 我待bug如初戀. 終會有xxx的那一天的! 加油!