admin管理员组

文章数量:1619183

最近项目测试环境从公有云切换到私有云环境,代码未做改变,但是服务端访问数据库老是失败,查看日志发现以下信息:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:Communications link failure 

从信息可以看出是因为jdbc与mysql之间的连接断了导致的。笔者所在项目组使用的是阿里巴巴的druid连接池,版本为1.1.0,下方是项目出错时的druid配置:

spring:
  datasource:
    url: ${url}
    username: ${username}
    password: ${pwd}
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    validation-query: SELECT 1;#数据库连接存活性检查语句
    time-between-eviction-runs-millis: 3600000

配置类:
@Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

由于笔者有自己开发过数据库连接池,因此首先想到的就是查看druid连接池核心源码,以下三图是druid数据库连接有效性检查的关键代码:

 

 

       其中testOnborrow与testOnreturn默认值都是false,如果设置为true,那么每次从连接池获取数据库连接和归还数据库连接都要发sql去数据库检查有效性,对性能不太友好,不建议设置为true。因此我们的目标只能放到testWhileIdle这个参数上了。

       上图源码显示testWhileIdle默认设置为true,如果数据库连接空闲时间大于timeBetweenEvictionRunsMillis,会执行有效性检查sql检测连接是否有效。这样就避免了每次从连接池获取数据库连接都去检查有效性,我们只要确保mysql的连接空闲等待时间大于timeBetweenEvictionRunsMillis即可。

      下面查看下mysql的连接空闲等待时间,可以看出是1800秒,而项目设置的timeBetweenEvictionRunsMillis是3600_000毫秒,mysql的连接空闲等待时间只有druid的一半,看到这里基本也就知道该怎么做了。

协商后将mysql wait_timeout修改为28800秒,再修改druid配置为如下(其中timeBetweenEvictionRunsMillis设置为21600_000毫秒)后,顺利解决了Communications link failure的问题。

spring:
  datasource:
    url: ${url}
    username: ${username}
    password: ${pwd}
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    test-while-idle: true
    time-between-eviction-runs-millis: 21600000
    keep-alive: true
    min-evictable-idle-time-millis: 21600000
    validation-query: SELECT 1;

druid官方配置说明:https://github/alibaba/druid/blob/master/druid-spring-boot-starter/src/test/resources/config-template.properties

本文标签: CommunicationsmysqlLINKdruidfailure