• Druid1.2.12版本发布,新增连接池默认配置connectTimeout和socketTimeout详解


    新版本特性如下

    这个版本连接池默认增加配置connectTimeout和socketTimeout,增强了SQL Parser

    1. 连接池DruidDataSource支持新的配置connectTimeout和socketTimeout,分别都是10秒。这个默认值会减少因为网络丢包时导致的连接池无法创建链接。
    2. 修复连接池DruidDataSource#handleFatalError方法判断是否关闭逻辑不对的问题 #4724
    3. 修复StatFilter统计Statement执行SQL只记录第一条SQL的问题 #4921
    4. 修复ParameterizedOutputVisitorUtils#restore结果不对的问题 #4532
    5. SQL Parser增强对PolarDB-X的支持 #4927
    6. SQL Parser增强对Oceanbase的支持 #4833
    7. SQL Parser增强对MySQL的支持 #4916 #4817 #4825
    8. SQL Parser增强对Clickhouse的支持 #4833 #4881
    9. SQL Parser增强对DB2的支持 #4838
    10. SQL Parser增强对Oracle的支持
    连接池connectTimeout配置

    在源码com.alibaba.druid.pool.DruidAbstractDataSource#createPhysicalConnection()方法中新增了如下代码:

            if (connectTimeout > 0) {
                if (isMySql) {
                    physicalConnectProperties.put("connectTimeout", connectTimeout);
                } else if (isOracle) {
                    physicalConnectProperties.put("oracle.net.CONNECT_TIMEOUT", connectTimeout);
                } else if (driver != null && "org.postgresql.Driver".equals(driver.getClass().getName())) {
                    physicalConnectProperties.put("loginTimeout", connectTimeout);
                    physicalConnectProperties.put("socketTimeout", connectTimeout);
                }
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    对mysql、oracle、postgresql数据库驱动配置连接超时时间,在连接的时候生效,默认值:10000ms

    连接池socket-timeout配置

    在数据库出现宕机或网络宜昌市,jdbc的socket超时是必须的,由于TCP/IP结构,socket没有办法检测到网络错误,因此应用程序也不能检测到与数据库之间的连接是否已经断开。如果没有socket超时,应用程序会一直等待数据库返回结果。为了避免死连接,socket必须设置超时时间,通过设置超时时间,可以防止出现网络错误时一直等待的情况并缩短故障时间。

    在源码com.alibaba.druid.pool.DruidAbstractDataSource#createPhysicalConnection()中新增如下代码:

                if (socketTimeout > 0 && !netTimeoutError) {
                    try {
                      //默认sql执行10s
                        conn.setNetworkTimeout(netTimeoutExecutor, socketTimeout);
                    } catch (SQLFeatureNotSupportedException | AbstractMethodError e) {
                        netTimeoutError = true;
                    } catch (Exception ignored) {
                        // ignored
                    }
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    其中netTimeoutExecutor是SynchronousExecutor的实例对象

        class SynchronousExecutor implements Executor {
            @Override
            public void execute(Runnable command) {
                try {
                    command.run();
                } catch (AbstractMethodError error) {
                    netTimeoutError = true;
                } catch (Exception ignored) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("failed to execute command " + command);
                    }
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    SynchronousExecutor是在com.alibaba.druid.pool.DruidDataSource#init方法中进行初始化

    其中command的具体实现是com.mysql.cj.jdbc.ConnectionImpl.NetworkTimeoutSetter(mysql的具体实现)

        private static class NetworkTimeoutSetter implements Runnable {
            private final WeakReference<JdbcConnection> connRef;
            private final int milliseconds;
    
            public NetworkTimeoutSetter(JdbcConnection conn, int milliseconds) {
                this.connRef = new WeakReference(conn);
                this.milliseconds = milliseconds;
            }
    
            public void run() {
                JdbcConnection conn = (JdbcConnection)this.connRef.get();
                if (conn != null) {
                    synchronized(conn.getConnectionMutex()) {
                        ((NativeSession)conn.getSession()).setSocketTimeout(this.milliseconds);
                    }
                }
    
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    连接池query-timeout、transaction-query-timeout配置
    • query-timeout:设置JDBC驱动执行Statement语句的秒数,如果超过限制,则会抛出SQLTimeoutException,默认:0 单位:秒 无限制
    • transaction-query-timeout:设置JDBC驱动执行N个Statement语句的秒数(事务模式),如果超过限制,则会抛出SQLTimeoutException,默认:0 单位:秒 无限制

    具体实现代码在com.alibaba.druid.pool.DruidAbstractDataSource#initStatement中如下:

        void initStatement(DruidPooledConnection conn, Statement stmt) throws SQLException {
            boolean transaction = !conn.getConnectionHolder().underlyingAutoCommit;
    
            int queryTimeout = transaction ? getTransactionQueryTimeout() : getQueryTimeout();
    
            if (queryTimeout > 0) {
                stmt.setQueryTimeout(queryTimeout);
            }
        }
    
        public int getTransactionQueryTimeout() {
            if (transactionQueryTimeout <= 0) {
                return queryTimeout;
            }
    
            return transactionQueryTimeout;
        }
    
        public int getQueryTimeout() {
            return queryTimeout;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    总结

    看了上面的几个时间设置估计会有点懵逼,这么多时间怎么区分,先看一下从网上找到的图:

    超时时间区分

    高级别的timeout依赖于低级别的timeout,只有当低级别的timeout无误时,高级别的timeout才能确保正常;如:当socket timeout出问题时,高级别statement timeout和transaction timeout都将失效。statement timeout无法处理网络连接失败时的超时,它能做的仅仅是限制statement的操作时间,网络连接失败时的timeout必须交由JDBC来处理,JDBC的socket timeout会受到操作系统socket timeout设置的影响。

    GitHub地址:https://github.com/mingyang66/spring-parent

  • 相关阅读:
    苹果Mac电脑fcpx视频剪辑:Final Cut Pro中文最新 for mac
    数学建模学习(84):鲸鱼优化算法(WOA)对多目标函数的优化求解
    为什么开源大模型终将胜出?
    暴雪和网易分手百万玩家何去何从
    20231107-前端学习炫酷菜单效果和折叠侧边栏
    # EXCEL VBA批量获取excel标题内容并填写到当前文件中
    QT - 模型与视图
    Stm32_标准库_10_TIM_显示时间&日期
    GitHub Copilot 自动写代码插件使用体验
    如何让你的工作能力比别人强
  • 原文地址:https://blog.csdn.net/yaomingyang/article/details/126901144