Spring Boot 默认数据库连接池 —— HikariCP
# HikariCP 简介
HikariCP 是一个非常轻量级(130 KB 左右)且效率很高的 JDBC 连接池框架。
与已有的其它 JDBC 连接池技术(c3p0、dbcp2、tomcat、druid)相比,HikariCP 的速度非常快,因为它采用了以下技术:
- 字节码精简:优化代码,直至编译后的字节码最少;
- 优化代理和拦截器:减少代码量,如:HikariCP 的 Statement proxy 只有 100 行,是 BoneCP 的十分之一;
- 自定义集合类型
FastStatementList
代替ArrayList<Statement>
:避免每次get()
调用都进行范围检查,避免调用remove()
时从头到尾扫描; - 自定义集合类型
ConcurrentBag
:提高并发读写效率; - 其他的一些微观优化:尽管几乎无法衡量,但这些优化相结合可提高整体性能。
# hikariCP连接池属性配置选择
# 主要配置
1、dataSourceClassName 这是DataSourceJDBC驱动程序提供的类的名称。请查阅您的特定JDBC驱动程序的文档以获取此类名称,或参阅下表。注XA数据源不受支持。XA需要像bitronix这样的真正的事务管理器 。请注意,如果您正在使用jdbcUrl“旧式”基于DriverManager的JDBC驱动程序配置,则不需要此属性 。 默认值:无
2、jdbcUrl 该属性指示HikariCP使用“基于DriverManager的”配置。我们认为基于DataSource的配置(上图)由于各种原因(参见下文)是优越的,但对于许多部署来说,几乎没有显着差异。 在“旧”驱动程序中使用此属性时,您可能还需要设置该 driverClassName属性,但不要先尝试。 请注意,如果使用此属性,您仍然可以使用DataSource属性来配置您的驱动程序,实际上建议您使用URL本身中指定的驱动程序参数。 默认值:无
3、username 此属性设置从基础驱动程序获取连接时使用的默认身份验证用户名。请注意,对于DataSources,这通过调用DataSource.getConnection(username, password)基础DataSource 以非常确定的方式工作。但是,对于基于驱动程序的配置,每个驱动程序都不同。在基于驱动程序的情况下,HikariCP将使用此username属性来设置传递给驱动程序调用的user属性。如果这不是你所需要的,例如完全跳过这个方法并且调用。 默认值:无PropertiesDriverManager.getConnection(jdbcUrl, props)addDataSourceProperty("username", ...)
4、password 此属性设置从基础驱动程序获取连接时使用的默认身份验证密码。请注意,对于DataSources,这通过调用DataSource.getConnection(username, password)基础DataSource 以非常确定的方式工作。但是,对于基于驱动程序的配置,每个驱动程序都不同。在基于驱动程序的情况下,HikariCP将使用此password属性来设置传递给驱动程序调用的password属性。如果这不是你所需要的,例如完全跳过这个方法并且调用。 默认值:无PropertiesDriverManager.getConnection(jdbcUrl, props)addDataSourceProperty("pass", ...)
# 常用配置
5、autoCommit 此属性控制从池返回的连接的默认自动提交行为。它是一个布尔值。 默认值:true
6、 connectionTimeout 此属性控制客户端(即您)将等待来自池的连接的最大毫秒数。如果在没有可用连接的情况下超过此时间,则会抛出SQLException。最低可接受的连接超时时间为250 ms。 默认值:30000(30秒)
最佳实践:非特殊业务场景保持缺省30s连接超时即可
7、 idleTimeout 此属性控制允许连接在池中闲置的最长时间。 此设置仅适用于minimumIdle定义为小于maximumPoolSize。一旦池达到连接,空闲连接将不会退出minimumIdle。连接是否因闲置而退出,最大变化量为+30秒,平均变化量为+15秒。在超时之前,连接永远不会退出。值为0意味着空闲连接永远不会从池中删除。允许的最小值是10000ms(10秒)。这个比较好理解:当前池中有空闲连接且比允许的最小空闲连接多时,根据空闲超时时间来逐出。
默认值:600000(10分钟)
连接池会定时轮询检测哪些连接是空闲,并且空闲达到了idleTimeout配置的时间,但轮询间隔有时间差,一个空闲连接最大可空闲idleTimeout + 30s会逐出,平均是:idleTimeout + 15s。
houseKeeper 定时检查空闲连接,对于超过 minimumIdle 的那部分db连接,如果空闲时长大于 idleTimeout 则关闭 softEvictConnection()
8、 maxLifetime 此属性控制池中连接的最大生存期。正在使用的连接永远不会退休,只有在关闭后才会被删除。在逐个连接的基础上,应用较小的负面衰减来避免池中的大量消失。 我们强烈建议设置此值,并且应该比任何数据库或基础设施规定的连接时间限制短几秒。 值为0表示没有最大寿命(无限寿命),当然是idleTimeout设定的主题。 默认值:1800000(30分钟)
强烈建议设置该属性,可设置的比数据库或网络基础设施允许的最大连接时间小一些。 如数据库连接最大失效时间是8小时,可设置为4小时。
db连接从创建后超过最大存活时长 maxLifeTime 的时候 softEvictConnection()
驱除连接
9、connectionTestQuery 如果您的驱动程序支持JDBC4,我们强烈建议您不要设置此属性。这是针对不支持JDBC4的“传统”驱动程序Connection.isValid() API。这是在连接从池中获得连接以确认与数据库的连接仍然存在之前将要执行的查询。再一次,尝试运行没有此属性的池,如果您的驱动程序不符合JDBC4的要求,HikariCP将记录一个错误以告知您。 默认值:无
最佳实践:驱动支持JDBC4不需要设置,反之需要配置,MYSQL: select 1; Oracle: select 1 from dual
10、minimumIdle 该属性控制HikariCP尝试在池中维护的最小空闲连接数。如果空闲连接低于此值并且连接池中的总连接数少于此值maximumPoolSize,则HikariCP将尽最大努力快速高效地添加其他连接。但是,为了获得最佳性能和响应尖峰需求,我们建议不要设置此值,而是允许HikariCP充当固定大小的连接池。
默认值:与maximumPoolSize相同
最佳实践:保持缺省,让连接池固定大小,避免扩缩容带来的性能影响
11、maximumPoolSize 此属性控制池允许达到的最大大小,包括空闲和正在使用的连接。基本上这个值将决定到数据库后端的最大实际连接数。对此的合理价值最好由您的执行环境决定。当池达到此大小并且没有空闲连接可用时,对getConnection()的调用将connectionTimeout在超时前阻塞达几毫秒。 默认值:10
最佳实践:根据实际环境配置,通常设置为核心数的2倍较优
12、metricRegistry 该属性仅通过编程配置或IoC容器可用。该属性允许您指定池使用的Codahale / Dropwizard 实例MetricRegistry来记录各种指标。有关 详细信息,请参阅Metrics维基页面。 默认值:无
13、healthCheckRegistry 该属性仅通过编程配置或IoC容器可用。该属性允许您指定池使用的Codahale / Dropwizard 的实例HealthCheckRegistry来报告当前的健康信息。有关 详细信息,请参阅健康检查 wiki页面。 默认值:无
14、poolName 此属性表示连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置。 默认:自动生成
最佳的配置如下:
# 不常用配置
15、 initializationFailTimeout 如果池无法成功初始化连接,则此属性控制池是否将“快速失败”。任何正数都取为尝试获取初始连接的毫秒数; 应用程序线程将在此期间被阻止。如果在超时发生之前无法获取连接,则会引发异常。此超时被应用后的connectionTimeout 期。如果值为零(0),HikariCP将尝试获取并验证连接。如果获得连接但未通过验证,将抛出异常并且池未启动。但是,如果无法获得连接,则会启动该池,但后续获取连接的操作可能会失败。小于零的值将绕过任何初始连接尝试,并且在尝试获取后台连接时,池将立即启动。因此,以后努力获得连接可能会失败。 默认值:1
16、isolateInternalQueries 此属性确定HikariCP是否在其自己的事务中隔离内部池查询,例如连接活动测试。由于这些通常是只读查询,因此很少有必要将它们封装在自己的事务中。该属性仅适用于autoCommit禁用的情况。 默认值:false
17、allowPoolSuspension 该属性控制池是否可以通过JMX暂停和恢复。这对于某些故障转移自动化方案很有用。当池被暂停时,呼叫 getConnection()将不会超时,并将一直保持到池恢复为止。 默认值:false
18、readOnly 此属性控制默认情况下从池中获取的连接是否处于只读模式。注意某些数据库不支持只读模式的概念,而其他数据库则在Connection设置为只读时提供查询优化。无论您是否需要此属性,都将主要取决于您的应用程序和数据库。 默认值:false
19、registerMbeans 该属性控制是否注册JMX管理Bean(“MBeans”)。 默认值:false
20、catalog 该属性设置默认目录为支持目录的概念数据库。如果未指定此属性,则使用由JDBC驱动程序定义的默认目录。 默认:驱动程序默认
21、connectionInitSql 该属性设置一个SQL语句,在将每个新连接创建后,将其添加到池中之前执行该语句。如果这个SQL无效或引发异常,它将被视为连接失败并且将遵循标准重试逻辑。 默认值:无
22、driverClassName HikariCP将尝试通过DriverManager仅基于驱动程序来解析驱动程序jdbcUrl,但对于一些较旧的驱动程序,driverClassName还必须指定它。除非您收到明显的错误消息,指出找不到驱动程序,否则请忽略此属性。 默认值:无
23、transactionIsolation 此属性控制从池返回的连接的默认事务隔离级别。如果未指定此属性,则使用由JDBC驱动程序定义的默认事务隔离级别。如果您有针对所有查询通用的特定隔离要求,请仅使用此属性。此属性的值是从不断的名称Connection 类,如TRANSACTION_READ_COMMITTED,TRANSACTION_REPEATABLE_READ等 默认值:驱动程序默认
24、 validationTimeout 此属性控制连接测试活动的最长时间。这个值必须小于connectionTimeout。最低可接受的验证超时时间为250 ms。 默认值:5000
25、 leakDetectionThreshold 此属性控制在记录消息之前连接可能离开池的时间量,表明可能存在连接泄漏。值为0意味着泄漏检测被禁用。启用泄漏检测的最低可接受值为2000(2秒)。 默认值:0
26、 dataSource 此属性仅通过编程配置或IoC容器可用。这个属性允许你直接设置DataSource池的实例,而不是让HikariCP通过反射来构造它。这在一些依赖注入框架中可能很有用。当指定此属性时,dataSourceClassName属性和所有DataSource特定的属性将被忽略。 默认值:无
27、schema 该属性设置的默认模式为支持模式的概念数据库。如果未指定此属性,则使用由JDBC驱动程序定义的默认模式。 默认:驱动程序默认
28、 threadFactory 此属性仅通过编程配置或IoC容器可用。该属性允许您设置java.util.concurrent.ThreadFactory将用于创建池使用的所有线程的实例。在一些只能通过ThreadFactory应用程序容器提供的线程创建线程的有限执行环境中需要它。 默认值:无
29、 scheduledExecutor 此属性仅通过编程配置或IoC容器可用。该属性允许您设置java.util.concurrent.ScheduledExecutorService将用于各种内部计划任务的实例。如果为ScheduledThreadPoolExecutor 实例提供HikariCP,建议setRemoveOnCancelPolicy(true)使用它。 默认值:无
# 总结
SpringBoot配置:
## Spring HikariConfig
# 事务自动提交 - 默认值:true
spring.datasource.hikari.auto-commit=true
# 连接测试查询 - Using the JDBC4 <code>Connection.isValid()</code> method to test connection validity can be more efficient on some databases and is recommended.
# 如果你的驱动程序支持JDBC4,强烈建议不要设置此属性。
spring.datasource.hikari.connection-test-query=select 1
# 连接超时时间 - 默认值:30秒。
spring.datasource.hikari.connection-timeout=30000
# 连接池中允许闲置的最长时间 - 默认值:10分钟
spring.datasource.hikari.idle-timeout=600000
# 一个连接生命时长(毫秒),超时而没被使用则被释放 - 默认值:30分钟
spring.datasource.hikari.max-lifetime=1800000
# 连接池中允许的最大连接数,包括闲置和使用中的连接 - 默认值:10
spring.datasource.hikari.maximum-pool-size=100
# 连接池中允许的最小空闲连接数 - 默认值:10。
spring.datasource.hikari.minimum-idle=10
# 连接被测试活动的最长时间 - 默认值:5秒。
spring.datasource.hikari.validation-timeout=5000
# 指定连接池的名称 - 默认自动生成
spring.datasource.hikari.pool-name=HikaraPool-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
打印结果
name=carpool.pool.ActiveConnections, value=0 //活跃的连接数
name=carpool.pool.IdleConnections, value=5 //空闲连接数
name=carpool.pool.MaxConnections, value=50 //最大连接数
name=carpool.pool.MinConnections, value=5 //最小连接数
name=carpool.pool.PendingConnections, value=0 //正在等待连接的线程数量。若大于0,则可适当调整最大连接数,即maxPoolSize
name=carpool.pool.TotalConnections, value=5 //总连接数,=ActiveConnections+IdleConnections
//创建连接时间,单位(ms)
name=carpool.pool.ConnectionCreation, count=64, min=20, max=42, mean=25.239365469394595, stddev=4.144925017857287, median=25.0, p75=27.0, p95=35.0, p98=41.0, p99=41.0, p999=41.0
//连接从池中取出到返回的时间,单位(ms)
name=carpool.pool.Usage, count=12, min=1, max=161, mean=16.40175308587677, stddev=37.07048983720169, median=5.0, p75=7.0, p95=90.0, p98=161.0, p99=161.0, p999=161.0
//连接超时比率
name=carpool.pool.ConnectionTimeoutRate, count=0, mean_rate=0.0, m1=0.0, m5=0.0, m15=0.0, rate_unit=events/second
//连接等待时间,单位(ms)
name=carpool.pool.Wait, count=12, min=0.0216, max=3.9868, mean=2.4306451410980117, stddev=1.1203468694566339, median=1.9914, p75=3.8614, p95=3.9868, p98=3.9868, p99=3.9868, p999=3.9868, mean_rate=0.016386862556643685, m1=6.626702430113693E-6, m5=0.05700412699378474, m15=0.2729751908786262, rate_unit=events/second, duration_unit=milliseconds
2
3
4
5
6
7
8
9
10
11
12
13
14