欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品

主頁(yè) > 知識(shí)庫(kù) > 低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限

低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限

熱門標(biāo)簽:云南電商智能外呼系統(tǒng)價(jià)格 高清地圖標(biāo)注道路 外東北地圖標(biāo)注 話務(wù)外呼系統(tǒng)怎么樣 拉卡拉外呼系統(tǒng) 大眾點(diǎn)評(píng)星級(jí)酒店地圖標(biāo)注 智能外呼系統(tǒng)復(fù)位 400電話可以辦理嗎 臨清電話機(jī)器人

現(xiàn)象

應(yīng)用升級(jí)MySQL驅(qū)動(dòng)8.0后,在并發(fā)量較高時(shí),查看監(jiān)控打點(diǎn),Druid連接池拿到連接并執(zhí)行SQL的時(shí)間大部分都超過200ms

對(duì)系統(tǒng)進(jìn)行壓測(cè),發(fā)現(xiàn)出現(xiàn)大量線程阻塞的情況,線程dump信息如下:

"http-nio-5366-exec-48" #210 daemon prio=5 os_prio=0 tid=0x00000000023d0800 nid=0x3be9 waiting for monitor entry [0x00007fa4c1400000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:66)
        - waiting to lock 0x0000000775af0960> (a java.lang.Object)
        at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1186)
        at com.alibaba.druid.util.Utils.loadClass(Utils.java:220)
        at com.alibaba.druid.util.MySqlUtils.getLastPacketReceivedTimeMs(MySqlUtils.java:372)

根因分析

public class MySqlUtils {

    public static long getLastPacketReceivedTimeMs(Connection conn) throws SQLException {
        if (class_connectionImpl == null  !class_connectionImpl_Error) {
            try {
                class_connectionImpl = Utils.loadClass("com.mysql.jdbc.MySQLConnection");
            } catch (Throwable error){
                class_connectionImpl_Error = true;
            }
        }

        if (class_connectionImpl == null) {
            return -1;
        }

        if (method_getIO == null  !method_getIO_error) {
            try {
                method_getIO = class_connectionImpl.getMethod("getIO");
            } catch (Throwable error){
                method_getIO_error = true;
            }
        }

        if (method_getIO == null) {
            return -1;
        }

        if (class_MysqlIO == null  !class_MysqlIO_Error) {
            try {
                class_MysqlIO = Utils.loadClass("com.mysql.jdbc.MysqlIO");
            } catch (Throwable error){
                class_MysqlIO_Error = true;
            }
        }

        if (class_MysqlIO == null) {
            return -1;
        }

        if (method_getLastPacketReceivedTimeMs == null  !method_getLastPacketReceivedTimeMs_error) {
            try {
                Method method = class_MysqlIO.getDeclaredMethod("getLastPacketReceivedTimeMs");
                method.setAccessible(true);
                method_getLastPacketReceivedTimeMs = method;
            } catch (Throwable error){
                method_getLastPacketReceivedTimeMs_error = true;
            }
        }

        if (method_getLastPacketReceivedTimeMs == null) {
            return -1;
        }

        try {
            Object connImpl = conn.unwrap(class_connectionImpl);
            if (connImpl == null) {
                return -1;
            }

            Object mysqlio = method_getIO.invoke(connImpl);
            Long ms = (Long) method_getLastPacketReceivedTimeMs.invoke(mysqlio);
            return ms.longValue();
        } catch (IllegalArgumentException e) {
            throw new SQLException("getLastPacketReceivedTimeMs error", e);
        } catch (IllegalAccessException e) {
            throw new SQLException("getLastPacketReceivedTimeMs error", e);
        } catch (InvocationTargetException e) {
            throw new SQLException("getLastPacketReceivedTimeMs error", e);
        }
    }

MySqlUtils中的getLastPacketReceivedTimeMs()方法會(huì)加載com.mysql.jdbc.MySQLConnection這個(gè)類,但在MySQL驅(qū)動(dòng)8.0中類名改為com.mysql.cj.jdbc.ConnectionImpl,所以MySQL驅(qū)動(dòng)8.0中加載不到com.mysql.jdbc.MySQLConnection

getLastPacketReceivedTimeMs()方法實(shí)現(xiàn)中,如果Utils.loadClass("com.mysql.jdbc.MySQLConnection")加載不到類并拋出異常,會(huì)修改變量class_connectionImpl_Error,下次調(diào)用不會(huì)再進(jìn)行加載

public class Utils {

    public static Class?> loadClass(String className) {
        Class?> clazz = null;

        if (className == null) {
            return null;
        }

        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            // skip
        }

        ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
        if (ctxClassLoader != null) {
            try {
                clazz = ctxClassLoader.loadClass(className);
            } catch (ClassNotFoundException e) {
                // skip
            }
        }

        return clazz;
    }

但是,在Utils的loadClass()方法中同樣catch了ClassNotFoundException,這就導(dǎo)致loadClass()在加載不到類的時(shí)候,并不會(huì)拋出異常,從而會(huì)導(dǎo)致每調(diào)用一次getLastPacketReceivedTimeMs()方法,就會(huì)加載一次MySQLConnection這個(gè)類

線程dump信息中可以看到是在調(diào)用TomcatEmbeddedWebappClassLoader的loadClass()方法時(shí),導(dǎo)致線程阻塞的

public class TomcatEmbeddedWebappClassLoader extends ParallelWebappClassLoader {

 public Class?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
  synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name)) {
   Class?> result = findExistingLoadedClass(name);
   result = (result != null) ? result : doLoadClass(name);
   if (result == null) {
    throw new ClassNotFoundException(name);
   }
   return resolveIfNecessary(result, resolve);
  }
 }

這是因?yàn)門omcatEmbeddedWebappClassLoader在加載類的時(shí)候,會(huì)加synchronized鎖,這就導(dǎo)致每調(diào)用一次getLastPacketReceivedTimeMs()方法,就會(huì)加載一次com.mysql.jdbc.MySQLConnection,而又始終加載不到,在加載類的時(shí)候會(huì)加synchronized鎖,所以會(huì)出現(xiàn)線程阻塞,性能下降的現(xiàn)象

getLastPacketReceivedTimeMs()方法調(diào)用時(shí)機(jī)

public abstract class DruidAbstractDataSource extends WrapperAdapter implements DruidAbstractDataSourceMBean, DataSource, DataSourceProxy, Serializable {

    protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
        String sqlFile = JdbcSqlStat.getContextSqlFile();
        String sqlName = JdbcSqlStat.getContextSqlName();

        if (sqlFile != null) {
            JdbcSqlStat.setContextSqlFile(null);
        }
        if (sqlName != null) {
            JdbcSqlStat.setContextSqlName(null);
        }
        try {
            if (validConnectionChecker != null) {
                boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
                long currentTimeMillis = System.currentTimeMillis();
                if (holder != null) {
                    holder.lastValidTimeMillis = currentTimeMillis;
                    holder.lastExecTimeMillis = currentTimeMillis;
                }

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

                if (valid  onFatalError) {
                    lock.lock();
                    try {
                        if (onFatalError) {
                            onFatalError = false;
                        }
                    } finally {
                        lock.unlock();
                    }
                }

                return valid;
            }

            if (conn.isClosed()) {
                return false;
            }

            if (null == validationQuery) {
                return true;
            }

            Statement stmt = null;
            ResultSet rset = null;
            try {
                stmt = conn.createStatement();
                if (getValidationQueryTimeout() > 0) {
                    stmt.setQueryTimeout(validationQueryTimeout);
                }
                rset = stmt.executeQuery(validationQuery);
                if (!rset.next()) {
                    return false;
                }
            } finally {
                JdbcUtils.close(rset);
                JdbcUtils.close(stmt);
            }

            if (onFatalError) {
                lock.lock();
                try {
                    if (onFatalError) {
                        onFatalError = false;
                    }
                } finally {
                    lock.unlock();
                }
            }

            return true;
        } catch (Throwable ex) {
            // skip
            return false;
        } finally {
            if (sqlFile != null) {
                JdbcSqlStat.setContextSqlFile(sqlFile);
            }
            if (sqlName != null) {
                JdbcSqlStat.setContextSqlName(sqlName);
            }
        }
    }

只有DruidAbstractDataSource的testConnectionInternal()方法中會(huì)調(diào)用getLastPacketReceivedTimeMs()方法

testConnectionInternal()是用來檢測(cè)連接是否有效的,在獲取連接和歸還連接時(shí)都有可能會(huì)調(diào)用該方法,這取決于Druid檢測(cè)連接是否有效的參數(shù)

Druid檢測(cè)連接是否有效的參數(shù):

  • testOnBorrow:每次獲取連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效(會(huì)影響性能)
  • testOnReturn:每次歸還連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效(會(huì)影響性能)
  • testWhileIdle:申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測(cè)連接是否有效
  • 應(yīng)用中設(shè)置了testOnBorrow=true,每次獲取連接時(shí),都會(huì)去搶占synchronized鎖,所以性能下降的很明顯

解決方案

經(jīng)驗(yàn)證,使用Druid 1.x版本=1.1.22會(huì)出現(xiàn)該bug,解決方案就是升級(jí)至Druid 1.x版本>=1.1.23或者Druid 1.2.x版本

GitHub issue:https://github.com/alibaba/druid/issues/3808

到此這篇關(guān)于低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限的文章就介紹到這了,更多相關(guān)MySQL驅(qū)動(dòng)8.0低版本Druid連接池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • MySQL 8.0 驅(qū)動(dòng)與阿里druid版本兼容問題解決
  • MySql 8.0及對(duì)應(yīng)驅(qū)動(dòng)包匹配的注意點(diǎn)說明
  • 關(guān)于Mysql8.0版本驅(qū)動(dòng)getTables返回所有庫(kù)的表問題淺析
  • 詳解Mybatis逆向工程中使用Mysql8.0版本驅(qū)動(dòng)遇到的問題

標(biāo)簽:三明 揚(yáng)州 定西 阿里 無錫 溫州 山西 福州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限》,本文關(guān)鍵詞  低,版本,Druid,連接,池,+MySQL,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于低版本Druid連接池+MySQL驅(qū)動(dòng)8.0導(dǎo)致線程阻塞、性能受限的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    欧美阿v视频在线大全_亚洲欧美中文日韩V在线观看_www性欧美日韩欧美91_亚洲欧美日韩久久精品
  • <rt id="w000q"><acronym id="w000q"></acronym></rt>
  • <abbr id="w000q"></abbr>
    <rt id="w000q"></rt>
    在线观看视频91| 亚洲女人的天堂| 美腿丝袜亚洲三区| 不卡一区二区在线观看| 666欧美在线视频| 亚洲国产aⅴ成人精品无吗| 波多野结衣电影免费观看| 色综合欧美在线| 亚洲日本青草视频在线怡红院 | 国产精品一区免费在线观看| 欧美日韩高清丝袜| 日韩免费在线观看| 伦理电影国产精品| 9.1片黄在线观看| 欧美激情中文不卡| 成人深夜福利app| 日本电影亚洲天堂一区| 亚洲综合色自拍一区| 国产免费无码一区二区| 5月丁香婷婷综合| 蜜桃在线一区二区三区| 亚洲v国产v欧美v久久久久久| 久久色.com| 国产黑丝在线一区二区三区| 无码黑人精品一区二区| 亚洲视频你懂的| 稀缺小u女呦精品呦| 日韩网站在线看片你懂的| 免费三级欧美电影| 手机免费观看av| 亚洲特黄一级片| 人妻 丝袜美腿 中文字幕| 欧美男男青年gay1069videost | 欧美电影免费观看高清完整版在线观看 | 欧美色图校园春色| 欧美精品色综合| 免费在线观看成人| 成人涩涩小片视频日本| 亚洲女性喷水在线观看一区| 亚洲av成人精品一区二区三区 | 国产黑丝在线观看| 91精品国产综合久久精品性色| 久久99国产精品免费网站| 多男操一女视频| 一区二区三区精品| 波多野结衣av在线观看| 国产日韩欧美不卡在线| 亚洲国产综合av| 欧美一区二区精品| 国产成人精品一区二区三区四区 | 日韩av片在线免费观看| 亚洲视频免费看| 手机在线看片日韩| 久久精品免视看| 国产黄色一区二区三区| 欧美电影免费提供在线观看| 成人精品鲁一区一区二区| 3d动漫精品啪啪1区2区免费| 国产精品99久久久久久有的能看| 欧美在线免费观看亚洲| 美女国产一区二区三区| 日本高清免费不卡视频| 免费xxxx性欧美18vr| 国产88在线观看入口| 日韩成人免费在线| 波多野结衣不卡视频| 日韩av中文字幕一区二区三区| 亚洲熟女毛茸茸| 视频一区国产视频| 色综合久久99| 日韩av在线发布| 91久久免费观看| 经典三级在线一区| 欧美日韩不卡视频| 国产成人在线观看免费网站| 91 com成人网| aa级大片欧美| 久久午夜国产精品| 中文字幕三级电影| 自拍偷拍亚洲激情| 在线免费观看视频| 视频一区在线视频| 在线免费观看一区| 国产白丝精品91爽爽久久| 日韩三级在线免费观看| 91论坛在线播放| 中文字幕av免费专区久久| 亚洲午夜久久久久久久久红桃| 亚洲精品第一国产综合野| 999福利视频| 视频一区二区国产| 欧美亚洲综合久久| 成人av电影在线网| 国产欧美精品日韩区二区麻豆天美| 国产情侣久久久久aⅴ免费| 日韩一区在线播放| 男女全黄做爰文章| 久久精品国产亚洲一区二区三区| 欧美高清视频一二三区| 99国产欧美另类久久久精品| 国产拍揄自揄精品视频麻豆| 亚洲天堂视频一区| 日韩和的一区二区| 欧美女孩性生活视频| a4yy欧美一区二区三区| 国产精品网站在线| 日韩av片在线免费观看| 久久成人久久鬼色| 日韩精品一区国产麻豆| 日韩www视频| 亚洲国产成人高清精品| 欧美亚洲日本一区| av中文字幕一区| 中文字幕色av一区二区三区| 国产精品99久久久久久成人| 国产伦精品一区二区三区免费迷| 久久免费偷拍视频| 免费一级做a爰片久久毛片潮| 蜜臀精品久久久久久蜜臀| 欧美一区二区三区影视| 中文字幕人妻一区二区三区| 香蕉久久夜色精品国产使用方法| 欧美日韩国产一二三| 无码人妻一区二区三区在线| 亚洲福利国产精品| 91精品国产综合久久蜜臀 | 日韩亚洲欧美在线| 黄色工厂在线观看| 蜜臀av一级做a爰片久久| 欧美v日韩v国产v| 亚洲精品91在线| 国产一区二区三区免费| 欧美激情在线一区二区三区| 日日噜噜夜夜狠狠久久波多野| 成人黄色软件下载| 亚洲嫩草精品久久| 欧美日韩精品久久久| 亚洲 欧美 日韩在线| 热久久国产精品| 欧美精品一区二区三区四区 | 青青草97国产精品免费观看无弹窗版| 欧美日韩成人激情| 久久久久久久久久久国产精品| 蓝色福利精品导航| 国产欧美日韩综合| 国产又黄又爽又无遮挡| 手机在线播放av| 视频一区二区欧美| 久久影院午夜论| 黄色片子在线观看| 91蜜桃婷婷狠狠久久综合9色| 亚洲一区国产视频| 欧美大胆人体bbbb| 亚洲成av人片www| 日韩免费一区二区| 久久嫩草捆绑紧缚| 91在线视频免费观看| 调教+趴+乳夹+国产+精品| 精品国产乱码久久久久久夜甘婷婷| 亚洲激情图片网| 99视频一区二区| 婷婷六月综合网| 精品国产91亚洲一区二区三区婷婷| 欧美性生给视频| 麻豆免费在线观看视频| 美国毛片一区二区| 国产精品家庭影院| 在线成人免费视频| 毛片久久久久久| 91麻豆免费看| 久久国产麻豆精品| 亚洲人成网站精品片在线观看| 欧美一级一区二区| 午夜三级在线观看| 国产精品久久久久久亚洲av| 国模少妇一区二区三区| 一区二区视频在线看| 2023国产精品自拍| 欧洲一区二区av| 90岁老太婆乱淫| 97久久久精品综合88久久| 日本欧美大码aⅴ在线播放| 国产精品九色蝌蚪自拍| 日韩一区二区三区av| 国产传媒免费在线观看| 99精品一区二区三区无码吞精| 国产成人午夜高潮毛片| 亚洲一区二区三区爽爽爽爽爽| 久久亚洲综合av| 欧美美女一区二区在线观看| 久久久久99精品成人| 老熟女高潮一区二区三区| 极品美女销魂一区二区三区免费| 亚洲欧美日韩国产中文在线| 精品99久久久久久| 欧美性xxxxxxxx| 国产精品精品软件男同| 人人妻人人澡人人爽人人精品| 97精品久久久午夜一区二区三区 | 午夜精品久久久久久久久|