Spring Boot 2.x中使用HikariCP作为默认的数据连接池。 HikariCP使用Javassist字节码操作库来实现动态代理,优化并精简了字节码,同时内部使用com.zaxxer.hikari.util.FastList代替ArrayList、使用了更好的并发集合类com.zaxxer.hikari.util.ConcurrentBag,“号称”是目前最快的数据库连接池。

基本使用

在Spring Boot 2.x中使用HikariCP十分简单,只需引入依赖implementation 'org.springframework.boot:spring-boot-starter-jdbc'

 1pluginManagement {
 2	repositories {
 3		gradlePluginPortal()
 4	}
 5}
 6rootProject.name = 'datasource-config'
 7
 8plugins {
 9	id 'org.springframework.boot' version '2.1.3.RELEASE'
10	id 'java'
11}
12
13apply plugin: 'io.spring.dependency-management'
14
15group = 'spring-boot-guides'
16version = '0.0.1-SNAPSHOT'
17sourceCompatibility = '1.8'
18
19repositories {
20	mavenCentral()
21}
22
23dependencies {
24	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
25	runtimeOnly 'com.h2database:h2'
26	testImplementation 'org.springframework.boot:spring-boot-starter-test'
27}

配置文件如下:

 1spring:
 2  datasource:
 3    url: jdbc:h2:mem:demodb
 4    username: sa
 5    password:
 6    hikari: # https://github.com/brettwooldridge/HikariCP (uses milliseconds for all time values)
 7      maximumPoolSize: 10
 8      minimumIdle: 2
 9      idleTimeout: 600000
10      connectionTimeout: 30000
11      maxLifetime: 1800000

关于连接池的具体配置参数详见HikariCP

示例代码如下:

 1package springbootguides.datasourceconfig;
 2
 3import org.springframework.beans.factory.annotation.Autowired;
 4import org.springframework.boot.CommandLineRunner;
 5import org.springframework.boot.SpringApplication;
 6import org.springframework.boot.autoconfigure.SpringBootApplication;
 7
 8import javax.sql.DataSource;
 9import java.sql.Connection;
10
11@SpringBootApplication
12public class DatasourceConfigApplication implements CommandLineRunner {
13
14	@Autowired
15	private DataSource datasource;
16
17	@Override
18	public void run(String... args) throws Exception {
19		try(Connection conn = datasource.getConnection()) {
20			System.out.println(conn);
21		}
22	}
23
24	public static void main(String[] args) {
25		SpringApplication.run(DatasourceConfigApplication.class, args);
26	}
27
28}

实现原理

Spring Boot使用如下方式整合HikariCP:入口是org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,通过org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari中的@Bean方式创建com.zaxxer.hikari.HikariDataSource

 1/**
 2	 * Hikari DataSource configuration.
 3	 */
 4	@ConditionalOnClass(HikariDataSource.class)
 5	@ConditionalOnMissingBean(DataSource.class)
 6	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource", matchIfMissing = true)
 7	static class Hikari {
 8
 9		@Bean
10		@ConfigurationProperties(prefix = "spring.datasource.hikari")
11		public HikariDataSource dataSource(DataSourceProperties properties) {
12			HikariDataSource dataSource = createDataSource(properties,
13					HikariDataSource.class);
14			if (StringUtils.hasText(properties.getName())) {
15				dataSource.setPoolName(properties.getName());
16			}
17			return dataSource;
18		}
19
20	}

@ConfigurationProperties(prefix = "spring.datasource.hikari")会自动把spring.datasource.hikari.*相关的连接池配置信息注入到创建的HikariDataSource实例中。

HikariCP的监控和遥测

因为在我们的微服务体系中使用的监控系统是Prometheus,这里以Prometheus为例。

注意spring boot 2.0对spring boot 1.x的metrics进行了重构,不再向后兼容,主要是在spring-boot-acutator中使用了micrometer,支持了更多的监控系统:Atlas、Datadog、Ganglia、Graphite、Influx、JMX、NewRelic、Prometheus、SignalFx、StatsD、Wavefront。Spring boot 2.0的metrics对比spring boot 1.x除了引入micrometer外,更大的体现是支持了tag,这也说明Prometheus、Influx等支持Tag的时序监控数据模型的监控系统已经成为主流。

在前面示例中的build.gradle中加入如下依赖:

1implementation 'org.springframework.boot:spring-boot-starter-web'
2implementation 'org.springframework.boot:spring-boot-starter-actuator'
3implementation 'io.micrometer:micrometer-registry-prometheus'

配置文件applycation.yaml中加入对actuator的配置:

1management:
2  endpoints:
3    web:
4      exposure:
5        include: "health,info,prometheus"
6  server:
7    port: 8079
8    servlet:
9      context-path: /

注意这里引入了web和actuator依赖,通过配置management.server.port指定actuator的web端点为8089端口,通过 management.endpoints.include对外开放/actuator/prometheus,在引入io.micrometer:micrometer-registry-prometheus依赖之后,端点/actuator/prometheus当即生效。

 1curl http://localhost:8079/actuator/prometheus | grep hikari
 2# TYPE hikaricp_connections_acquire_seconds summary
 3hikaricp_connections_acquire_seconds_count{pool="HikariPool-1",} 3.0
 4hikaricp_connections_acquire_seconds_sum{pool="HikariPool-1",} 0.001230082
 5# HELP hikaricp_connections_acquire_seconds_max Connection acquire time
 6# TYPE hikaricp_connections_acquire_seconds_max gauge
 7hikaricp_connections_acquire_seconds_max{pool="HikariPool-1",} 0.0
 8# HELP hikaricp_connections_min Min connections
 9# TYPE hikaricp_connections_min gauge
10hikaricp_connections_min{pool="HikariPool-1",} 2.0
11# TYPE hikaricp_connections_timeout_total counter
12hikaricp_connections_timeout_total{pool="HikariPool-1",} 0.0
13# HELP hikaricp_connections_pending Pending threads
14# TYPE hikaricp_connections_pending gauge
15hikaricp_connections_pending{pool="HikariPool-1",} 0.0
16# HELP hikaricp_connections_usage_seconds Connection usage time
17# TYPE hikaricp_connections_usage_seconds summary
18hikaricp_connections_usage_seconds_count{pool="HikariPool-1",} 3.0
19hikaricp_connections_usage_seconds_sum{pool="HikariPool-1",} 0.06
20# HELP hikaricp_connections_usage_seconds_max Connection usage time
21# TYPE hikaricp_connections_usage_seconds_max gauge
22hikaricp_connections_usage_seconds_max{pool="HikariPool-1",} 0.0
23# HELP hikaricp_connections_max Max connections
24# TYPE hikaricp_connections_max gauge
25hikaricp_connections_max{pool="HikariPool-1",} 10.0
26# HELP hikaricp_connections Total connections
27# TYPE hikaricp_connections gauge
28hikaricp_connections{pool="HikariPool-1",} 2.0
29# HELP hikaricp_connections_creation_seconds_max Connection creation time
30# TYPE hikaricp_connections_creation_seconds_max gauge
31hikaricp_connections_creation_seconds_max{pool="HikariPool-1",} 0.0
32# HELP hikaricp_connections_creation_seconds Connection creation time
33# TYPE hikaricp_connections_creation_seconds summary
34hikaricp_connections_creation_seconds_count{pool="HikariPool-1",} 1.0
35hikaricp_connections_creation_seconds_sum{pool="HikariPool-1",} 0.001
36# HELP hikaricp_connections_idle Idle connections
37# TYPE hikaricp_connections_idle gauge
38hikaricp_connections_idle{pool="HikariPool-1",} 2.0
39# HELP hikaricp_connections_active Active connections
40# TYPE hikaricp_connections_active gauge
41hikaricp_connections_active{pool="HikariPool-1",} 0.0

参考