zoukankan      html  css  js  c++  java
  • 【转】Alibaba 的 druid 报错 discard long time none received connection. 问题

    https://blog.51cto.com/u_15101595/2625323

    在使用了新版的 druid 以后,日志中一直在报 Error,内容是 discard long time none received connection. , jdbcUrl : 巴拉巴拉,但程序运行并没有受到影响,但看着一大片错误就浑身难受,我决定去他们的源码里看看到底是怎么回事。网上搜索到的解决方案是回退到1.1.22可解决,但我觉得这样的解决方案有点傻X,不去想解决问题,而是倒车躲避。

    看看源码是谁在报错

            进到源码搜索这句「discard long time none received connection.」报错,在「com.alibaba.druid.pool.DruidAbstractDataSource#testConnectionInternal(com.alibaba.druid.pool.DruidConnectionHolder, java.sql.Connection)」找到如下代码:

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

            我来解释一下,MySqlUtils.getLastPacketReceivedTimeMs(conn) 是获取上一次使用的时间,mysqlIdleMillis 就是计算出来空闲的时间,timeBetweenEvictionRunsMillis 是个写死的值 60秒,if (lastPacketReceivedTimeMs > 0 && mysqlIdleMillis >= timeBetweenEvictionRunsMillis) 就是如果连接空闲了 60秒以上,那就 discardConnection(holder) 丢弃这个旧连接并顺带打印了一个日志 LOG.warn(errorMsg)。

    明白原理以后做点什么

             经过我Google查询一通,有个人给出了一个方法,可以配置「druid.mysql.usePingMethod=false」原理是让验证空闲连接使用 select 1,而不是使用MySQL的Ping,这样就刷新了上次使用时间,不会出现空闲 60秒以上的连接,在运行参数中增加:-Ddruid.mysql.usePingMethod=false

            查看valid变量赋值的地方,跟踪源码在MySqlValidConnectionChecker类的configFromProperties的方法中可以看到可以配置变量druid.mysql.usePingMethod=false,这样就不会通过ping的方式去检查链接的有效性,从而不会打印该error log。durid版本1.2.1

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

    阿里他们为什么要清空空闲60秒以上的连接

            我猜测,阿里他们给数据库设置的数据库空闲等待时间是60秒,mysql数据库到了空闲等待时间将关闭空闲的连接,以提升数据库服务器的处理能力。MySQL的默认空闲等待时间是8小时,就是「wait_timeout」的配置值。如果数据库主动关闭了空闲的连接,而连接池并不知道,还在使用这个连接,就会产生异常。

  • 相关阅读:
    SGU 495 Kids and Prizes 概率DP 或 数学推理
    poj 2799 IP Networks 模拟 位运算
    uva 202 Repeating Decimals 模拟
    poj 3158 Kickdown 字符串匹配?
    uva 1595 Symmetry 暴力
    uva 201 Squares 暴力
    uva 1594 Ducci Sequence 哈希
    uva 1368 DNA Consensus String 字符串
    数字、字符串、列表的常用操作
    if条件判断 流程控制
  • 原文地址:https://www.cnblogs.com/zkwarrior/p/14858421.html
Copyright © 2011-2022 走看看