前言:
某个项目,开发过程中需要连接多个数据源,多数据源部分就不说了,在Spring Boot中其实就是手动构造不同的 datasource交给IOC容器,然后根据持久层框架 Mabatis 或者是 JPA之类的,明确下 数据源和持久层的绑定关系即可,直白说就是 调某个方法时用对应的数据源即可。
因为,项目中主要都是数据库的查询,而且,前端页面的设计,会在某个页面同时访问多个接口,缓存没有的情况下,会导致蛮多数据库操作,涉及 多个线程 操作 一个或者多个数据源。
自然想到:用连接池的方式,类似于线程池,复用连接,节省创建和回收的开销,缩短响应时间。
于是,网上一番调研,首先吸引我注意力的是 Druid,网上资料很多,不赘述。
Druid使用时遇到的问题:
连接数据库: Oracle (怀疑有可能是数据库配置问题,但是数据库在第三方,无法操作。。。)
使用版本:1.1.5
配置均为常规配置: testOnBorrow 为 false removeAbandoned 为 false
问题:日志经常打印出如下异常:
com.alibaba.druid.util.JdbcUtils - close statement error java.sql.SQLRecoverableException: 关闭的连接 com.alibaba.druid.util.JdbcUtils - close connection error java.sql.SQLRecoverableException: 无法从套接字读取更多的数据 com.alibaba.druid.pool.GetConnectionTimeoutException: wait millis 10, active 0, maxActive xxx
使用此版本,服务上线之后,几十分钟便不可访问,需要重启才行。
问题猜测:可能存在连接泄露的情况,于是加入 超时强制回收配置如下
当有线程超时持有连接时,强制回收,并打印日志信息。
加入此配置之后,服务可一直运行,查日志时,有 超时强制回收的日志打印出来,但是对应到具体的代码行,就是个 简单查询的SQL,执行时间较短,不清楚因为什么导致了 连接泄露。
换用新版本:逛着逛着逛到了Druid 的 GitHub,立马注意到有了新的版本:1.1.14. 升级版本,重新运行。 这次的情况是,异常还是会报,但是在 不配置超时强制回收(abandon相关选项)的情况下,服务也不会无故进入不可用的情况了。
最后策略:一直抛异常也是扎心了,设置超时强制回收也不是长久之计,遂决定换个数据库连接池。
换用 Hikari连接池:
换了 Hikari,配置比 Druid简单点,服务上线后正常运行,到写这边Blog时,除了数据库语法异常外,没有出现其他的问题。
总结:
感觉问题不一定在 Druid,因为只有 Oracle有这个问题,其他的 Mysql和SQLServer 均未出现问题,这个以后有机会得拿Oracle再测试下。
性能方面 说下自己用了两个连接池的不严谨的感觉,没有测试过自己的服务,也可能是心理原因,前端页面感知上,用 Hikari的时候 响应会迅速些,大部分在可接受的范围内。
总之,后面有机会再深入研究下。
2019年3月5日 追加:
被服务无故下线搞得有点敏感,经常打开页面查看响应情况 以及查看error日志,截止目前 并没有抛出数据库连接方面的异常,而且 可能因为热点代码被即时编译的原因,业务端感知服务性能提升了。