记一次数据库链接异常处理

背景描述

公司大力推行docker,我们原有的物理机数据库都要求迁移到公司的弹性数据库。我们原以为只是简单的修改一下数据库链接,然而并不是,第二天就有了线上问题。

抛出的异常

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
cause by:
Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost

分析问题

看异常的原因是因为,使用了失效的数据库链接。这个时候我们首先想到的是数据库连接池的配置有问题,然后我又充分了解了链接池配置的参数:

喽了一篇我们的链接池配置,testOnBorrow设置的为false,所以果断改成了true,然后再上线。
可惜报错!
然后我们再看报错异常,发现报出异常显示我们使用的是tomcat连接池??我们一直以为自己使用的是DBCP??这里先说一下我们的应用的技术环境:我们使用的Springboot1框架。所以我就去查了下,springboot1默认连接池是什么?没有在网上找到有人说这个事情,但是找到了所谓的可以指定配置连接池的方法。设置参数:
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
然后我又去上线了。
可惜还是报错!
然后我就怀疑人生了,难道我写的有问题?所以我决定去撸源码,看springboot是如何指定数据源的,看到了如下代码:

@SuppressWarnings("unchecked")
public Class<? extends DataSource> findType() {
    if (this.type != null) {
        return this.type;
    }
    for (String name : DATA_SOURCE_TYPE_NAMES) {
        try {
            return (Class<? extends DataSource>) ClassUtils.forName(name,
                    this.classLoader);
        }
        catch (Exception ex) {
            // Swallow and continue
        }
    }
    return null;
}

private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
        "org.apache.tomcat.jdbc.pool.DataSource",
        "com.zaxxer.hikari.HikariDataSource",
        "org.apache.commons.dbcp.BasicDataSource", // deprecated
        "org.apache.commons.dbcp2.BasicDataSource" };

可以看到遍历数组,第一个元素为jdbc.pool,问题是并没有找到关于spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource的配置!!!不知道网上的文章是哪里抄来的,而且真的很误导人。后来找到了如下正确的配置方式:
DataSourceBuilder.create().type(org.apache.commons.dbcp2.BasicDataSource.class).build()
然我再次上线,但是发现还是报错!!

公司特殊环境

上述我也说了,我们接入的是公司弹性数据库。所谓弹性数据库,是在传统数据库基础上应用了docker容器化技术,做的一种可自动调整的数据库服务。简单原理如下图所示:

可以看到它是增加了一层数据库网关的,我们的应用连接的是数据库网关。到了这种时候我们只能找dba了,他让我们配置这两个参数:
socketTimeout=20000&connectTimeout=10000,我在网上查了查这些参数的含义:
connectTimeout:表示的是数据库驱动(mysql-connector-java)与mysql服务器建立TCP连接的超时时间。
socketTimeout:是通过TCP连接发送数据(在这里就是要执行的sql)后,等待响应的超时时间。
我其实抱着怀疑的态度配置上的,因为我认为这两个参数和我的连接失效并没有关系。但是我上线后,居然没有再报错了!!!我去询问dba原因,他也说不出个所以然来(大公司基本都这样)。我个人怀疑他们的网关层,应该是根据这个机制做了什么事情,但是具体做了什么,我也就不清楚了。

如果感到快乐,你就拍拍手。