最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot集成Druid出現(xiàn)異常報(bào)錯(cuò)的原因及解決

 更新時(shí)間:2021年05月27日 11:20:01   作者:程序新世界  
Druid 可以很好的監(jiān)控 DB 池連接和 SQL 的執(zhí)行情況,天生就是針對(duì)監(jiān)控而生的 DB 連接池。本文講述了Spring Boot集成Druid項(xiàng)目中discard long time none received connection異常的解決方法,出現(xiàn)此問(wèn)題的同學(xué)可以參考下

Spring Boot集成Druid異常

在Spring Boot集成Druid項(xiàng)目中,發(fā)現(xiàn)錯(cuò)誤日志中頻繁的出現(xiàn)如下錯(cuò)誤信息:

discard long time none received connection. , jdbcUrl : jdbc:mysql://******?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8, version : 1.2.3, lastPacketReceivedIdleMillis : 172675

經(jīng)過(guò)排查發(fā)現(xiàn)是Druid版本導(dǎo)致的異常,在1.2.2及以前版本并未出現(xiàn)如此異常。而在其以上版本均存在此問(wèn)題,下面就來(lái)分析一下異常原因及解決方案。

異常分析

首先上面的異常并不影響程序的正常運(yùn)行,但作為程序員看到程序中不停的出現(xiàn)異常還是難以忍受的。所以還是要刨根問(wèn)底的解決一下的。

跟蹤堆棧信息會(huì)發(fā)現(xiàn)對(duì)應(yīng)的異常是從com.alibaba.druid.pool.DruidAbstractDataSource#testConnectionInternal方法中拋出的,對(duì)應(yīng)的代碼如下:

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
                    + ", jdbcUrl : " + jdbcUrl
                    + ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
            LOG.error(errorMsg);
            return false;
        }
    }
}

上述代碼中,MySqlUtils.getLastPacketReceivedTimeMs(conn) 是獲取上一次使用的時(shí)間,mysqlIdleMillis 就是計(jì)算出來(lái)空閑的時(shí)間,timeBetweenEvictionRunsMillis 是常量60秒。如果連接空閑了60秒以上,那就discardConnection(holder) 丟棄這個(gè)舊連接并順帶打印了一個(gè)日志LOG.warn(errorMsg)。

原理追蹤

在上述代碼中,我們看到進(jìn)入該業(yè)務(wù)邏輯是有前提條件的,也就是valid和isMySql變量同時(shí)為true。isMySql為true是必須的,我們使用的本身就是Mysql數(shù)據(jù)庫(kù)。那么是否可以讓valid為false呢?這樣不就不會(huì)進(jìn)入該業(yè)務(wù)處理了嗎?

來(lái)看看valid的來(lái)源,還是在該方法的上面:

boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);

我們找到validConnectionChecker的Mysql實(shí)現(xiàn)子類MySqlValidConnectionChecker,該類中對(duì)isValidConnection的實(shí)現(xiàn)如下:

public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
    if (conn.isClosed()) {
        return false;
    }

    if (usePingMethod) {
        if (conn instanceof DruidPooledConnection) {
            conn = ((DruidPooledConnection) conn).getConnection();
        }

        if (conn instanceof ConnectionProxy) {
            conn = ((ConnectionProxy) conn).getRawObject();
        }

        if (clazz.isAssignableFrom(conn.getClass())) {
            if (validationQueryTimeout <= 0) {
                validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
            }

            try {
                ping.invoke(conn, true, validationQueryTimeout * 1000);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SQLException) {
                    throw (SQLException) cause;
                }
                throw e;
            }
            return true;
        }
    }

    String query = validateQuery;
    if (validateQuery == null || validateQuery.isEmpty()) {
        query = DEFAULT_VALIDATION_QUERY;
    }

    Statement stmt = null;
    ResultSet rs = null;
    try {
        stmt = conn.createStatement();
        if (validationQueryTimeout > 0) {
            stmt.setQueryTimeout(validationQueryTimeout);
        }
        rs = stmt.executeQuery(query);
        return true;
    } finally {
        JdbcUtils.close(rs);
        JdbcUtils.close(stmt);
    }

}

我們可以看到上述方法中有三個(gè)返回的地方:第一個(gè)連接已關(guān)閉;第二個(gè)使用ping的形式進(jìn)行檢查;第三,使用select 1的方式進(jìn)行檢查。而使用ping的形式檢查時(shí),無(wú)論是否拋異常都會(huì)返回true。這里我們禁用該模式即可。

進(jìn)入ping的業(yè)務(wù)邏輯主要靠變量usePingMethod來(lái)判斷,追蹤代碼會(huì)發(fā)現(xiàn)在這里進(jìn)行的設(shè)置:

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);
    }
}

那么,也就是說(shuō),當(dāng)我們把系統(tǒng)屬性druid.mysql.usePingMethod設(shè)置為false即可禁用該功能。

禁用Ping Method

找到了問(wèn)題的根源,那么剩下的就是如何禁用了,通常有三種形式。

第一,在啟動(dòng)程序時(shí)在運(yùn)行參數(shù)中增加:-Ddruid.mysql.usePingMethod=false。

第二,在Spring Boot項(xiàng)目中,可在啟動(dòng)類中添加如下靜態(tài)代碼快:

static {
    System.setProperty("druid.mysql.usePingMethod","false");
}

第三,類文件配置。在項(xiàng)目的DruidConfig類中新增加:

/*
* 解決druid 日志報(bào)錯(cuò):discard long time none received connection:xxx
* */
@PostConstruct
public void setProperties(){
    System.setProperty("druid.mysql.usePingMethod","false");
}

至此,已可以成功關(guān)閉該功能,異常信息再也不會(huì)出現(xiàn)了。

為什么要清空空閑60秒以上的連接

猜測(cè),阿里給數(shù)據(jù)庫(kù)設(shè)置的數(shù)據(jù)庫(kù)空閑等待時(shí)間是60秒,mysql數(shù)據(jù)庫(kù)到了空閑等待時(shí)間將關(guān)閉空閑的連接,以提升數(shù)據(jù)庫(kù)服務(wù)器的處理能力。

MySQL的默認(rèn)空閑等待時(shí)間是8小時(shí),就是「wait_timeout」的配置值。如果數(shù)據(jù)庫(kù)主動(dòng)關(guān)閉了空閑的連接,而連接池并不知道,還在使用這個(gè)連接,就會(huì)產(chǎn)生異常。

以上就是Spring Boot集成Druid出現(xiàn)異常報(bào)錯(cuò)的原因及解決的詳細(xì)內(nèi)容,更多關(guān)于Spring Boot集成Druid出現(xiàn)異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java GZip 基于內(nèi)存實(shí)現(xiàn)壓縮和解壓的方法

    Java GZip 基于內(nèi)存實(shí)現(xiàn)壓縮和解壓的方法

    這篇文章主要介紹了Java GZip 基于內(nèi)存實(shí)現(xiàn)壓縮和解壓的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Java 實(shí)戰(zhàn)項(xiàng)目錘煉之校園宿舍管理系統(tǒng)的實(shí)現(xiàn)流程

    Java 實(shí)戰(zhàn)項(xiàng)目錘煉之校園宿舍管理系統(tǒng)的實(shí)現(xiàn)流程

    讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+jsp+javaweb+mysql+ajax實(shí)現(xiàn)一個(gè)校園宿舍管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • java 多線程死鎖詳解及簡(jiǎn)單實(shí)例

    java 多線程死鎖詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了java 多線程死鎖詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Spring Boot詳細(xì)打印啟動(dòng)時(shí)異常堆棧信息詳析

    Spring Boot詳細(xì)打印啟動(dòng)時(shí)異常堆棧信息詳析

    這篇文章主要給大家介紹了關(guān)于Spring Boot詳細(xì)打印啟動(dòng)時(shí)異常堆棧信息的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Spring Boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java使用注解實(shí)現(xiàn)防止重復(fù)提交實(shí)例

    Java使用注解實(shí)現(xiàn)防止重復(fù)提交實(shí)例

    這篇文章主要介紹了Java使用注解實(shí)現(xiàn)防止重復(fù)提交實(shí)例,在一些項(xiàng)目中由于用戶誤操作,多次點(diǎn)擊表單提交按鈕,會(huì)產(chǎn)生很多次的數(shù)據(jù)交互,為了解決這一問(wèn)題,本文使用注解來(lái)實(shí)現(xiàn)防止重復(fù)提交,需要的朋友可以參考下
    2023-07-07
  • SpringAop自定義切面注解、自定義過(guò)濾器及ThreadLocal詳解

    SpringAop自定義切面注解、自定義過(guò)濾器及ThreadLocal詳解

    這篇文章主要介紹了SpringAop自定義切面注解、自定義過(guò)濾器及ThreadLocal詳解,Aspect(切面)通常是一個(gè)類,里面可以定義切入點(diǎn)和通知(切面 = 切點(diǎn)+通知),execution()是最常用的切點(diǎn)函數(shù),需要的朋友可以參考下
    2024-01-01
  • java使用httpclient發(fā)送post請(qǐng)求示例

    java使用httpclient發(fā)送post請(qǐng)求示例

    這篇文章主要介紹了java使用httpclient發(fā)送post請(qǐng)求示例,依賴JSON、HTTPClient等jar包,需要的朋友可以參考下
    2014-02-02
  • mybatis快速入門學(xué)習(xí)教程新手注意問(wèn)題小結(jié)

    mybatis快速入門學(xué)習(xí)教程新手注意問(wèn)題小結(jié)

    MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的持久層框架。接下來(lái)通過(guò)本文給大家介紹mybatis快速入門學(xué)習(xí)教程新手注意問(wèn)題小結(jié),需要的朋友可以參考下
    2017-02-02
  • Java 實(shí)戰(zhàn)項(xiàng)目錘煉之網(wǎng)上花店商城的實(shí)現(xiàn)流程

    Java 實(shí)戰(zhàn)項(xiàng)目錘煉之網(wǎng)上花店商城的實(shí)現(xiàn)流程

    讀萬(wàn)卷書不如行萬(wàn)里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+jsp+servlet+mysql+ajax實(shí)現(xiàn)一個(gè)網(wǎng)上花店商城系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • Spring中@PostConstruct的實(shí)現(xiàn)方法

    Spring中@PostConstruct的實(shí)現(xiàn)方法

    大多數(shù)java程序員都使用過(guò)@PostConstruct注解,它的作用就是在Bean初始化完成后執(zhí)行,相當(dāng)于我們常說(shuō)的init()方法,但是我們看@PostConstruct只有單單的一個(gè)注解,它到底是如何實(shí)現(xiàn)在Bean初始化完成后就被調(diào)用的呢,本文將詳細(xì)給大家介紹一下
    2023-06-06

最新評(píng)論

宜宾县| 禹城市| 阆中市| 政和县| 攀枝花市| 海丰县| 通海县| 阿勒泰市| 佛坪县| 星座| 凉城县| 岫岩| 乃东县| 武威市| 汉源县| 安塞县| 临桂县| 抚州市| 博野县| 西城区| 丰宁| 久治县| 德州市| 崇信县| 尚志市| 柏乡县| 依安县| 从江县| 霍邱县| 宕昌县| 保定市| 宜兴市| 福贡县| 玉屏| 洪泽县| 朔州市| 星子县| 双柏县| 鱼台县| 靖西县| 招远市|