连接池
HikariCP
HikariCP 来自于日语,意为:光。 它本身作为 SpringBoot 2.X 默认的连接池。
"Fast"源于深度优化和大量小改进
- 字节码级别优化(很多方法通过 JavaAssist 生成)
- 大量小改进:用 FastStatementList 代替 ArrayList、无锁集合 ConcurrentBag 、 代理类的优化(用 invokestatic 代替 invokevirtual)
SpringBoot 中的配置
- 默认使用 HikariCP
- application.properties 配置格式 spring.datasource.hikari.*
- 如果是 SpringBoot 1.x 需要在 maven 中移除默认的 tomcat-jdbc 依赖,并且引入 HikariCP 的 Maven 依赖,并且在
application.properties
配置文件中指定默认的连接池类型spring.datasource.type=com.zaxxer.hikari.HikariDataSource
1# 暴露Actuator
2management.endpoints.web.exposure.include=*
3
4# 如果你的终端支持ANSI,设置彩色输出会让日志更具可读性
5# DETECT:会检查终端是否支持ANSI,是的话就采用彩色输出(推荐项)
6# ALWAYS:总是使用ANSI-colored格式输出,若终端不支持的时候,会有很多干扰信息,不推荐
7spring.output.ansi.enabled=ALWAYS
8
9# 通用配置
10spring.datasource.url=jdbc:h2:mem:testdb
11spring.datasource.username=sa
12spring.datasource.password=
13#spring.datasource.driver-class-name=com.mysql.jdbc.Driver #(可选),因为springboot会根据spring.datasource.url 自动判断,选择合适的驱动。
14
15# 连接池配置
16spring.datasource.hikari.maximumPoolSize=5
17spring.datasource.hikari.minimumIdle=5
18spring.datasource.hikari.idleTimeout=600000
19spring.datasource.hikari.connectionTimeout=30000
20spring.datasource.hikari.maxLifetime=1800000
常用配置说明
name | description | default_value |
---|---|---|
maximumPoolSize | 此属性控制允许池达到的最大大小,包括空闲和使用中的连接。基本上,此值将确定到数据库后端的最大实际连接数。合理的值最好由您的执行环境确定。当池达到此大小并且没有空闲连接可用时,对 getConnection()的调用将 connectionTimeout 在超时之前最多阻塞毫秒。 |
10 |
minimumIdle | 此属性控制 HikariCP 尝试在池中维护的最小空闲连接数。如果空闲连接下降到该值以下,并且池中的总连接数少于 maximumPoolSize ,则 HikariCP 将尽最大努力快速而有效地添加其他连接。但是,为了获得最佳性能和对峰值需求的响应能力,我们建议不要设置此值,而应让 HikariCP 充当固定大小的连接池。 默认值:与 maximumPoolSize 相同 |
10 |
maximumPoolSize | ||
idleTimeout | 连接允许在池中闲置的最长时间 | 600000(10 分钟) |
connectionTimeout | 此属性控制客户端(即您)等待来自池的连接的最大毫秒数。如果超过此时间而没有可用的连接,则会抛出 SQLException。可接受的最低连接超时为 250 ms。 | 30000(30 秒) |
maxLifetime | 用来设置一个 connection 在连接池中的存活时间 | 1800000,即 30 分钟。如果设置为 0,表示存活时间无限大。如果不等于 0 且小于 30 秒则会被重置回 30 分钟。 |
更多配置 | 官网 |
Alibaba Druid
“Druid 连接池是阿 ⾥巴巴开源的数据库连接池项 ⽬。Druid 连接池为监控而生,内置强 ⼤的监控功能,监控特性不影响性能。功能强 ⼤,能防 SQL 注 ⼊,内置 Logging 能诊断 Hack 应用行为。”
WiKi
- 详细的监控
- ExceptionSorter,针对主流数据的返回码都有支持
- SQL 防注入
- 内置加密配置
- 众多扩展点,方便进行定制
SpringBoot 方式
引入依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.1.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.data</groupId>
12 <artifactId>druid-demo</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>druid-demo</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-actuator</artifactId>
25 </dependency>
26 <dependency>
27 <groupId>org.springframework.boot</groupId>
28 <artifactId>spring-boot-starter-jdbc</artifactId>
29 <!-- 需要手动排除默认的连接池 HikariCP -->
30 <exclusions>
31 <exclusion>
32 <artifactId>HikariCP</artifactId>
33 <groupId>com.zaxxer</groupId>
34 </exclusion>
35 </exclusions>
36 </dependency>
37 <dependency>
38 <groupId>org.projectlombok</groupId>
39 <artifactId>lombok</artifactId>
40 </dependency>
41
42 <dependency>
43 <groupId>com.h2database</groupId>
44 <artifactId>h2</artifactId>
45 <scope>runtime</scope>
46 </dependency>
47 <dependency>
48 <groupId>org.springframework.boot</groupId>
49 <artifactId>spring-boot-starter-test</artifactId>
50 <scope>test</scope>
51 </dependency>
52 <!-- 引入 druid-spring-boot-starter -->
53 <dependency>
54 <groupId>com.alibaba</groupId>
55 <artifactId>druid-spring-boot-starter</artifactId>
56 <version>1.1.10</version>
57 </dependency>
58 </dependencies>
59
60 <build>
61 <plugins>
62 <plugin>
63 <groupId>org.springframework.boot</groupId>
64 <artifactId>spring-boot-maven-plugin</artifactId>
65 </plugin>
66 </plugins>
67 </build>
68</project>
application.properties
1spring.output.ansi.enabled=ALWAYS
2
3spring.datasource.url=jdbc:h2:mem:foo
4spring.datasource.username=sa
5spring.datasource.password=n/z7PyA5cvcXvs8px8FVmBVpaRyNsvJb3X7YfS38DJrIg25EbZaZGvH4aHcnc97Om0islpCAPc3MqsGvsrxVJw==
6
7spring.datasource.druid.initial-size=5
8spring.datasource.druid.max-active=5
9spring.datasource.druid.min-idle=5
10# Filter配置
11spring.datasource.druid.filters=conn,config,stat,slf4j
12
13# 密码加密
14spring.datasource.druid.connection-properties=config.decrypt=true;config.decrypt.key=${public-key}
15spring.datasource.druid.filter.config.enabled=true
16
17spring.datasource.druid.test-on-borrow=true
18spring.datasource.druid.test-on-return=true
19spring.datasource.druid.test-while-idle=true
20
21# druid-spring-boot-starter 默认就会开启统计功能的filter 所以注释掉了
22#spring.datasource.druid.filter.stat.enabled=true
23
24# 开启慢sql日志 (默认是监控那些执行超过3秒的sql语句)
25spring.datasource.druid.filter.stat.log-slow-sql=true
26# 默认抓取超过100毫秒的sql语句
27spring.datasource.druid.filter.stat.slow-sql-millis=100
28
29public-key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALS8ng1XvgHrdOgm4pxrnUdt3sXtu/E8My9KzX8sXlz+mXRZQCop7NVQLne25pXHtZoDYuMh3bzoGj6v5HvvAQ8CAwEAAQ==
启动类
1package geektime.spring.data.druiddemo;
2
3import lombok.extern.slf4j.Slf4j;
4import org.springframework.beans.factory.annotation.Autowired;
5import org.springframework.boot.CommandLineRunner;
6import org.springframework.boot.SpringApplication;
7import org.springframework.boot.autoconfigure.SpringBootApplication;
8import org.springframework.jdbc.core.JdbcTemplate;
9
10import javax.sql.DataSource;
11
12@SpringBootApplication
13@Slf4j
14public class DruidDemoApplication implements CommandLineRunner {
15 @Autowired
16 private DataSource dataSource;
17 @Autowired
18 private JdbcTemplate jdbcTemplate;
19
20 public static void main(String[] args) {
21 SpringApplication.run(DruidDemoApplication.class, args);
22 }
23
24 @Override
25 public void run(String... args) throws Exception {
26 log.info(dataSource.toString());
27 }
28}
控制台输出 发现 Connections 中包含 5 个连接
1CreateTime:"2020-01-07 13:33:11",
2 ActiveCount:0,
3 PoolingCount:5,
4 CreateCount:5,
5 DestroyCount:0,
6 CloseCount:0,
7 ConnectCount:0,
8 Connections:[
9 {ID:1409712092, ConnectTime:"2020-01-07 13:33:11", UseCount:0, LastActiveTime:"2020-01-07 13:33:11"},
10 {ID:1083759991, ConnectTime:"2020-01-07 13:33:11", UseCount:0, LastActiveTime:"2020-01-07 13:33:11"},
11 {ID:1135523296, ConnectTime:"2020-01-07 13:33:11", UseCount:0, LastActiveTime:"2020-01-07 13:33:11"},
12 {ID:36127072, ConnectTime:"2020-01-07 13:33:11", UseCount:0, LastActiveTime:"2020-01-07 13:33:11"},
13 {ID:1698182759, ConnectTime:"2020-01-07 13:33:11", UseCount:0, LastActiveTime:"2020-01-07 13:33:11"}
14 ]
15}
16
17# 如果有慢sql会显示
182020-01-08 17:36:04.426 ERROR 2004 --- [ Thread-3] c.alibaba.druid.filter.stat.StatFilter : slow sql 209 millis. select id from foo where id = 1 for update[]
Druid Filter
- ⽤于定制连接池操作的各种环节
- 可以继承 FilterEventAdapter 以便 ⽅便地实现 Filter
1package geektime.spring.data.druiddemo;
2
3import com.alibaba.druid.filter.FilterChain;
4import com.alibaba.druid.filter.FilterEventAdapter;
5import com.alibaba.druid.proxy.jdbc.ConnectionProxy;
6import lombok.extern.slf4j.Slf4j;
7
8import java.util.Properties;
9
10@Slf4j
11public class ConnectionLogFilter extends FilterEventAdapter {
12 /**
13 * 复写的方法名字 代表 扩展点所在的位置
14 */
15 @Override
16 public void connection_connectBefore(FilterChain chain, Properties info) {
17 log.info("BEFORE CONNECTION!");
18 }
19
20 @Override
21 public void connection_connectAfter(ConnectionProxy connection) {
22 log.info("AFTER CONNECTION!");
23 }
24}
- 修改 META-INF/druid-fifilter.properties 增加 Filter 配置
1druid.filters.conn=geektime.spring.data.druiddemo.ConnectionLogFilter
Spring 方式
引入依赖
1<dependency>
2 <groupId>com.alibaba</groupId>
3 <artifactId>druid</artifactId>
4 <version>1.1.0</version>
5 </dependency>
application.yml
1server:
2 port: 8091
3druid:
4 allow:
5 ip: 127.0.0.1
6 login:
7 user_name: root
8 password: root
9spring:
10 datasource:
11 driver-class-name: com.mysql.jdbc.Driver
12 url: jdbc:mysql://192.168.31.201:3306/shop?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false
13 username: root
14 password: 123456
15 type: com.alibaba.druid.pool.DruidDataSource
16 initial-size: 1
17 min-idle: 1
18 max-idle: 5
19 max-wait-millis: 60000
20 timeBetweenEvictionRunsMillis: 60000
21 # 配置一个连接在池中最小生存的时间,单位是毫秒
22 minEvictableIdleTimeMillis: 300000
23 validationQuery: SELECT 1 FROM DUAL
24 testWhileIdle: true
25 testOnBorrow: true
26 testOnReturn: false
27 maxPoolPreparedStatementPerConnectionSize: 20
28 # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
29 filters: stat,wall
30 # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
31 connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
DruidConfig
1package com.xdclass.couponapp.config;
2
3import com.alibaba.druid.pool.DruidDataSource;
4import com.alibaba.druid.support.http.StatViewServlet;
5import com.alibaba.druid.support.http.WebStatFilter;
6import org.springframework.beans.factory.annotation.Value;
7import org.springframework.boot.context.properties.ConfigurationProperties;
8import org.springframework.boot.web.servlet.FilterRegistrationBean;
9import org.springframework.boot.web.servlet.ServletRegistrationBean;
10import org.springframework.context.annotation.Bean;
11import org.springframework.context.annotation.Configuration;
12
13import javax.sql.DataSource;
14import java.util.HashMap;
15import java.util.Map;
16
17@Configuration
18public class DruidConfig {
19
20
21 @Value("${druid.login.user_name}")
22 private String userName;
23
24 @Value("${druid.login.password}")
25 private String password;
26
27 @Bean(name = "default_datadatasource")
28 @ConfigurationProperties(prefix = "spring.datasource")
29 public DataSource druidDataSource(){
30 return new DruidDataSource();
31 }
32
33 @Bean
34 public ServletRegistrationBean druidServlet() {
35 ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
36 servletRegistrationBean.setServlet(new StatViewServlet());
37 servletRegistrationBean.addUrlMappings("/druid/*");
38 Map<String, String> initParameters = new HashMap<>(3);
39 // 用户名
40 initParameters.put("loginUsername", userName);
41 // 密码
42 initParameters.put("loginPassword", password);
43 // 禁用HTML页面上的“Reset All”功能
44 initParameters.put("resetEnable", "false");
45 servletRegistrationBean.setInitParameters(initParameters);
46 return servletRegistrationBean;
47 }
48
49 @Bean
50 public FilterRegistrationBean filterRegistrationBean() {
51 FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
52 filterRegistrationBean.setFilter(new WebStatFilter());
53 filterRegistrationBean.addUrlPatterns("/*");
54 filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
55 return filterRegistrationBean;
56 }
57}
Druid 监控台
1# http://localhost:8091/druid
2 root
3 root
Durid 使用注意事项
- 没有特殊情况,不要在生产环境打开监控的 Servlet,负载情况以日志输出为基准。
- 没有连接泄漏可能的情况下,不要开启 removeAbandoned。(大量和使用 ORM 框架的情况下。)
- testXxx 的使用需要注意,性能开销比较大。
- 务必配置合理的超时时间。