druid discard long time none received connection問題解析

最新項目中用的druid鏈接數據庫遇到一個困擾好久的問題mysql

1 開始用的druid版本是1.1.22版本,因爲業務需求,單個鏈接須要執行好久,理論上不須要用到自動回收,但爲了安全,仍是加了自動回收,時間設置的2個小時。sql

問題來了,程序常常報The last packet successfully received from the server was XXXXX milliseconds ago.  The last packet sent successfully to the server was 0 mill
iseconds ago錯誤,網上搜索了下答案,有說配置項,改數據庫事件設置,試過都沒有解決,後續看到https://cloud.tencent.com/developer/article/1397508 分析,以爲有必定道理,就開始後續之路數據庫

2.druid包升級到1.2.2,原來的問題是沒有了,新的問題出現了,discard long time none received connection,又繼續網上搜索答案,出來的結果一塌糊塗,不少說版本回退到1.1.22,內心不禁的說wc,這...安全

有點扯,繼續進行搜索測試,修改配置項validationQuery,修改testWhileIdle,修改...繼續測試,問題依舊,又搜索到運行時添加druid.mysql.usePingMethod=false,可是沒說怎樣添加,沒辦法下載源碼進行查看,導入源碼後發現以下:ide

 if (valid && isMySql) { // unexcepted branch
                    long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
                    if (lastPacketReceivedTimeMs > 0) {
                        long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
                        if (lastPacketReceivedTimeMs > 0 //
                                && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
                            discardConnection(holder);
                            String errorMsg = "discard long time none received connection. "
                                    + ", jdbcUrl : " + jdbcUrl
                                    + ", version : " + VERSION.getVersionNumber()
                                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
                            LOG.warn(errorMsg);
                            return false;
                        }
                    }
                }

這在配置中加timeBetweenEvictionRunsMillis:1800000 就能夠了,我的理解是一次操做數據庫大於這個時間就會被清除,更直觀些就是查詢或其餘操做在數據庫執行時間,這裏單位是毫秒。測試

緊接着查看源碼druid.mysql.usePingMethod=false這個設置,既然網上有人說,就看看好使不,源碼以下:ui

 configFromProperties(System.getProperties());
    }

    @Override
    public void configFromProperties(Properties properties) {
        String property = properties.getProperty("druid.mysql.usePingMethod");
        if ("true".equals(property)) {
            setUsePingMethod(true);
        } else if ("false".equals(property)) {
            setUsePingMethod(false);
        }
    }

druid加載System.getProperties(),查看屬性中的druid.mysql.usePingMethod的對應值,若是false,就不用ping方法,否者用ping方法,進一步查看不用ping方法就是用默認select 1,System.getProperties()查看了下通常是系統的一些參數,可是能夠put(key,value),程序啓動時間加載進去就能夠,項目中用到了定時器(根據本身項目寫就能夠,加載一次就ok了),就在初始化時間設置了具體值,代碼以下:spa

public void contextInitialized(ServletContextEvent arg0) {
        try {
            System.getProperties().put("druid.mysql.usePingMethod", "false");
            // 獲取Scheduler實例
            scheduler = new StdSchedulerFactory().getScheduler();
...

而後取消timeBetweenEvictionRunsMillis設置進行測試,程序跑1個小時沒有任何問題,到此問題解決。code

druid我的使用總結:server

1.The last packet successfully received from the server was問題升級jar包,我是升級到1.2.2版本

2.discard long time none received connection問題不應程序狀況下設置timeBetweenEvictionRunsMillis參數(注意是毫秒),改程序下加System.getProperties().put("druid.mysql.usePingMethod", "false")

druid默認使用usePingMethod方法,此方法並不會更新鏈接返回時間,致使lastPacketReceivedTimeMs大於timeBetweenEvictionRunsMillis

網上其餘的方法感受要不理解太深,沒有給出具體實現,要不就是複製粘貼的,但願對遇到此問題的人有所幫助。

相關文章
相關標籤/搜索