Druid配置

一、连接池基本配置

  • initialSize(初始化连接数)
    根据应用的启动并发需求进行设置,通常建议设置为与minIdle相同的值,以确保应用启动时能够快速获取到数据库连接。
    示例:initialSize=5
  • minIdle(最小空闲连接数)
    根据应用平时的最大QPS和响应时间(RT)来计算,确保在业务高峰期有足够的空闲连接可用。
    示例:minIdle=10(具体值需根据实际情况调整)
  • maxActive(最大活跃连接数)
    根据应用峰值时的QPS和RT来计算,同时考虑数据库服务器的负载能力。
    示例:maxActive=50(具体值需根据实际情况调整)
  • maxWait(最大等待时间)
    设置线程在获取数据库连接时的最大等待时间,以避免因等待时间过长而导致的业务超时。
    示例:maxWait=3000(毫秒)

二、连接健康检查

  • validationQuery(验证查询)
    设置用于验证连接有效性的SQL语句。Druid提供了常用数据库的ValidConnectionChecker,如果数据库支持,则优先使用;否则,使用validationQuery。
    示例:对于MySQL,validationQuery=SELECT 1
  • testWhileIdle(空闲时检测)
    建议设置为true,以在连接空闲时进行检测,确保连接的有效性。
    示例:testWhileIdle=true
  • testOnBorrow(借出时检测)
    设置为false,以减少借出连接时的开销。因为每次借出都进行检测会影响性能。
    示例:testOnBorrow=false
  • testOnReturn(归还时检测)
    设置为false,以避免归还连接时的额外开销。
    示例:testOnReturn=false
  • timeBetweenEvictionRunsMillis(检测间隔时间)
    设置触发空闲连接健康检查的间隔时间。
    示例:timeBetweenEvictionRunsMillis=60000(毫秒)
  • minEvictableIdleTimeMillis(最小空闲时间)
    设置连接在被清理前的最小空闲时间。
    示例:minEvictableIdleTimeMillis=300000(毫秒)

三、性能监控与优化

  • 启用监控统计功能
    通过设置相关参数启用Druid的监控统计功能,以便实时监控连接池的使用情况和性能状况。
    示例:在Druid配置中设置filters=stat来启用监控统计。
  • 配置Web监控页面
    启用Druid的Web监控页面,可以方便地查看连接池的运行状态、SQL执行次数、慢查询次数等关键指标。
    示例:在Spring Boot应用中,可以通过配置druid.stat-view-servlet等参数来启用Web监控页面。
  • 调整连接池参数
    根据监控页面的数据和业务需求,不断调整连接池的参数,以达到最佳的性能表现。
    示例:根据活跃连接数、等待连接数等指标,调整maxActive、minIdle等参数。

四、其他注意事项

  • 连接泄露检测
    启用连接泄露检测功能,可以及时发现并处理连接泄露问题。
    示例:在Druid配置中设置removeAbandoned=true和removeAbandonedTimeout等参数。
  • 日志记录
    启用日志记录功能,可以记录SQL执行的时间、执行的SQL语句以及相关的异常信息,有助于问题的诊断和优化。
    示例:在Druid配置中设置logAbandoned=true等参数。
  • 安全性
    确保Druid配置的安全性,避免敏感信息泄露。例如,不要将数据库密码等敏感信息硬编码在配置文件中。

五、使用时遇见的问题

  • druid版本1.2.16,jdbc超时时间设置无效
    初始化连接池时,会首先重jdbcUrl上获取超时配置,但这里是写死了 jdbcUrl.startsWith(“jdbc:mysql://”)。而如果使用了其他的jdbc就会导致获取不到,如:jdbc:mariadb。
    当获取不到时,druid默认给设置成了10s,而对一些执行时间超10s的sql,则会被强制关闭。而且这个判断也存在错误,两个超时配置必须都配置socketTimeout才会生效。
public void init() throws SQLException {
       ...
            if (this.jdbcUrl != null) {
                this.jdbcUrl = this.jdbcUrl.trim();
                initFromWrapDriverUrl();
                initFromUrlOrProperties();
            }
            if (connectTimeout == 0) {
                socketTimeout = DEFAULT_TIME_CONNECT_TIMEOUT_MILLIS;
            }
            if (socketTimeout == 0) {
                socketTimeout = DEFAULT_TIME_SOCKET_TIMEOUT_MILLIS;
            }
          ...
    }
private void initFromUrlOrProperties() {
        if (jdbcUrl.startsWith("jdbc:mysql://")) {
            if (jdbcUrl.indexOf("connectTimeout=") != -1 || jdbcUrl.indexOf("socketTimeout=") != -1) {
                String[] items = jdbcUrl.split("(\\?|&)");
                for (int i = 0; i < items.length; i++) {
                    String item = items[i];
                    if (item.startsWith("connectTimeout=")) {
                        String strVal = item.substring("connectTimeout=".length());
                        setConnectTimeout(strVal);
                    } else if (item.startsWith("socketTimeout=")) {
                        String strVal = item.substring("socketTimeout=".length());
                        setSocketTimeout(strVal);
                    }
                }
            }

            Object propertyConnectTimeout = connectProperties.get("connectTimeout");
            if (propertyConnectTimeout instanceof String) {
                setConnectTimeout((String) propertyConnectTimeout);
            } else if (propertyConnectTimeout instanceof Number) {
                setConnectTimeout(((Number) propertyConnectTimeout).intValue());
            }

            Object propertySocketTimeout = connectProperties.get("socketTimeout");
            if (propertySocketTimeout instanceof String) {
                setSocketTimeout((String) propertySocketTimeout);
            } else if (propertySocketTimeout instanceof Number) {
                setSocketTimeout(((Number) propertySocketTimeout).intValue());
            }
        }
    }
  • 数据库主备切换后,服务长时间无法恢复
    数据库在切换时,如果服务中的数据库连接正好在执行sql,而sockettimeout未设置,导致这些连接一直是running状态,同时也无法被druid移除。如果进行并发测试,druid连接池拉满,导致后续的连接一直不可用。
    解决方案:
    JDBC URL 增加 connectTimeout 和 socketTimeout 配置
    根据实际业务评估minIdle、maxActive 大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值