springboot 搭配的 的 druid最新版本 警告 discard long time none received connection. 问题

        在使用了新版的 druid-1.2.5 以后,日志中一直在报 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

spring :
  datasource :
    druid:
      mysql:
        usePingMethod: false

 

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

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」的配置值。如果数据库主动关闭了空闲的连接,而连接池并不知道,还在使用这个连接,就会产生异常。

### JDBC 警告 `discard long time none received connection` 解决方法 在使用 Java 进行数据库连接时,尤其是在使用 Druid 连接池的情况下,可能会出现 `discard long time none received connection` 的警告信息。该警告表示数据库连接池中存在长时间未接收到数据的连接,这些连接可能已经被丢弃,通常与连接池的空闲超时机制有关[^2]。 此类问题虽然不会直接导致程序崩溃,但可能会影响系统的稳定性,并造成资源浪费。以下是一些可行的解决方案: #### 1. 升级 Druid 版本 某些旧版本Druid 对连接空闲时间的处理逻辑不够完善,升级到最新版本可以有效解决该问题。新版本通常对连接池的空闲连接管理进行了优化,减少了此类警告的出现频率[^4]。 #### 2. 调整连接池配置 在配置文件中,可以尝试调整以下参数以避免连接长时间空闲被丢弃: ```yaml druid: filters: stat,wall maxActive: 20 initialSize: 5 minIdle: 5 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false ``` 其中,`minEvictableIdleTimeMillis` 控制连接在池中保持空闲而不被回收的最长时间(单位为毫秒),适当增大该值可避免连接被过早丢弃[^3]。 #### 3. 自定义配置类设置连接属性 可以在 Druid 的配置类中显式设置相关属性,例如: ```java @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/test"); dataSource.setUsername("root"); dataSource.setPassword("password"); dataSource.setInitialSize(5); dataSource.setMinIdle(5); dataSource.setMaxActive(20); dataSource.setTimeBetweenEvictionRunsMillis(60000); dataSource.setMinEvictableIdleTimeMillis(300000); dataSource.setValidationQuery("SELECT 1"); dataSource.setTestWhileIdle(true); return dataSource; } ``` 通过这种方式可以更灵活地控制连接池的行为,避免因连接长时间未使用而被丢弃的情况发生。 #### 4. 检查网络与数据库状态 如果连接频繁被丢弃,也可能是由于数据库服务器端主动断开了空闲连接,或者网络不稳定导致连接中断。可以检查数据库的 `wait_timeout` 和 `interactive_timeout` 设置,适当延长超时时间以匹配应用的连接行为[^3]。 ###
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值