最近发现项目(项目使用框架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连接池。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。