Spring Boot 2.+的默认连接池HikariCP详解
一、Spring Boot 2.+默认连接池HikariCP
如果是Spring Boot2.+,那么默认的连接池就是Hikaricp,不需要再另外导入包和配置,可以看到控制台
启动信息HikariPool
启动信息HikariDataSource
我们在控制台看到了
HikariPool-1 - Starting...
HikariPool-1 - Start completed
Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
说明Spring Boot 2.+默认使用的就是连接池HikariCP
二、调整连接池参数
HikariCP连接池提供了默认值,如果有需要也可以在配置文件里进行调整参数
spring:
########-spring datasource-########
datasource:
#账号配置
url: jdbc:mysql://127.0.0.1:3306/retail_db?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: ENC(5raHicqGiQ1nEXKO+R9ykYwJUrD/+nbx)
password: ENC(1NiRLG1lUkzLSg3uerUwU0bIRCDYiZnX)
driver-class-name: com.mysql.cj.jdbc.Driver
#hikari数据库连接池
hikari:
pool-name: Retail_HikariCP
minimum-idle: 5 #最小空闲连接数量
idle-timeout: 180000 #空闲连接存活最大时间,默认600000(10分钟)
maximum-pool-size: 10 #连接池最大连接数,默认是10
auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true
max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000
connection-test-query: SELECT 1
三、HikariCP连接池速度快于其他连接池的原因
-
相比于普通连接池,在ConnectionProxy中使用ArrayList来存储Statement对象,HikariCP改用FatList来存储对象,而其中的区别是,ArrayList在每次执行get(Index)方法时,都需要对List的范围进行检查,而FastList不需要,在能确保范围的合法性的情况下,可以省去范围检查的开销。
-
另外在Java代码中,很多关于Connection的操作,都是在使用完之后直接关闭连接,以前都是从头到尾遍历,来关闭对应的Connection,而HikariCP则是从尾部对Connection集合进行扫描,整体上来说,从尾部开始的性能更好一些。
-
内部使用一个无锁的集合来存储,并对其中的切换操作做了优化。
-
从字节码指令的角度去优化,连接池使用
PROXY_FACTORY.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames))语句来建立statements,resultset等的实例,将其翻译成字节码指令后,会有如下的指令,0: getstatic和15: invokevirtual #69。将上述的方法改为使用 ProxyFactory.getProxyPreparedStatement(this, delegate.prepareStatement(sql, columnNames)),后,就不在需要0: getstatic指令,并且使用了12: invokestatic #67代替了15: invokevirtual #69,前者invokestatic 更容易被JIT优化。另外从堆栈的角度来说,堆栈大小也从原来的5变成了4。
四、HiKariCP和Druid对比
我们所熟知的C3P0,DBCP,Druid, HiKariCP为我们所常用的数据库连接池,其中C3P0已经很久没有更新了。DBCP更新速度很慢,基本处于不活跃状态,而Druid和HikariCP处于活跃状态的更新中,这就是我们说的二代产品了。
HiKariCP
- 字节码精简 :优化代码,直到编译后的字节码最少,这样,CPU缓存可以加载更多的程序代码;
- 优化代理和拦截器 :减少代码,例如HikariCP的Statement proxy只有100行代码,只有BoneCP的十分之一;
- 自定义数组类型(FastStatementList)代替ArrayList :避免每次get()调用都要进行range check,避免调用remove()时的从头到尾的扫描;
- 自定义集合类型(ConcurrentBag :提高并发读写的效率;
- 其他针对BoneCP缺陷的优化。
Druid
- Druid提供性能卓越的连接池功能外,还集成了SQL监控,黑名单拦截等功能,
- 强大的监控特性,通过Druid提供的监控功能,可以清楚知道连接池和SQL的工作情况。
- 监控SQL的执行时间、ResultSet持有时间、返回行数、更新行数、错误次数、错误堆栈信息;
- SQL执行的耗时区间分布。什么是耗时区间分布呢?比如说,某个SQL执行了1000次,其中01毫秒区间50次,110毫秒800次,10100毫秒100次,1001000毫秒30次,1~10秒15次,10秒以上5次。通过耗时区间分布,能够非常清楚知道SQL的执行耗时情况;
- 监控连接池的物理连接创建和销毁次数、逻辑连接的申请和关闭次数、非空等待次数、PSCache命中率等。
- 方便扩展。Druid提供了Filter-Chain模式的扩展API,可以自己编写Filter拦截JDBC中的任何方法,可以在上面做任何事情,比如说性能监控、SQL审计、用户名密码加密、日志等等。
总的来说:
1、HiKariCP性能比Druid高
2、HiKariCP是Spring Boot 2+官方支持,和Spring Boot兼容性更好
3、Druid的优势是监控完善,扩展性更好(但拦截过多也会增加框架复杂度以及框架性能)
具体选HiKariCP或Druid视团队具体需求而定