最近发现项目(项目使用框架springboot3,mybatis plus,druid,dynamic-datasource )中老是有下面两种报错

### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: Read timed out
; Read timed out] with root cause

和
DruidDataSource - recyle error

刚开始是怀疑sql执行时间过长,于是将sql优化后执行时间在1s内,发到线上之后发现问题没有解决,并且报错的sql并不是同一条sql,并有可能是单表的简单查询报错,所以上面的报错应该和sql没有关系。于是根据报错怀疑和连接池有关。

百度查询后有说是druid版本太低导致,所以升级版本后重新尝试,依旧无效。查看druid配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      initial-size: 20
      min-idle: 10
      max-active: 50
      max-wait: 300000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
    dynamic:
      strict: false

看配置没发现多大问题,只能进去druid源码查看。


druid的启动配置类是com.alibaba.druid.pool.DruidDataSource
查看public void init() throws SQLException 方法。

注意到初始化时的参数为

minIdle = 0
maxActive= 8
initialSize = 0

和我配置类的不一致,想到我的项目是多数据源的,使用了mybatis plus的dynamic-datasource 插件,而之前的配置方式是按照一般的druid数据源来配置,所以之前的参数设置一直没生效。


查询资料跟更改配置为(注意这里的druid配置是在dynamic下的

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    dynamic:
      strict: false
      druid:
        initial-size: 10
        min-idle: 10
        max-active: 50
        max-wait: 300000

启动后发现配置生效了,但是这个配置是对每个数据源都生效,所以每个数据源都会在启动时初始化10个连接,项目内并不是所有的数据源都需要这样处理。所以可以在主数据源下单独配置

spring:
  datasource:
    dynamic:
      primary: p1
      datasource:
        p1:
          url: xxx
          username: xxx
          password: xxx
          driver-class-name: com.mysql.cj.jdbc.Driver
          druid:
            max-active: 1024
            initial-size: 10
            min-idle: 10
            max-wait: 60000

重新上线后发现不再报错。之前的报错原因可以定位是之前的配置未生效,导致数据库连接池中的最大活跃连接只有8个,用户使用多时导致连接池连接数不够导致。更细致的原因还需查看druid的源码分析。

2024年4月25日更新:现在发现dynamic-datasource 可以使用默认的连接池hikari。线上观察下来druid的问题就不会在发生了。所以推荐在使用dynamic-datasource 的时候使用hikari连接池。


tao不是哭脸
119 声望3 粉丝