Spring Boot - 数据库集成07 - 数据库连接池

news/2025/2/1 13:49:02/

数据库连接池

文章目录

  • 数据库连接池
    • 一:知识准备
    • 二:HikariCP连接池
      • 1:简单使用
      • 2:进一步理解
        • 2.1:是SpringBoot2.x默认连接池
        • 2.2:为什么会成为默认连接池
    • 三: 集成数据库Druid连接池
      • 1:简单使用
      • 2:进一步理解
        • 2.1:更多功能
        • 2.2:如何评价阿里的Druid连接池

一:知识准备

1:什么是数据库连接池?

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;

释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

这项技术能明显提高对数据库操作的性能

2:数据库连接池基本原理

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。

使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。

而连接的建立、断开都由连接池自身来管理。

同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。

也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

在这里插入图片描述

数据库连接池的最小连接数和最大连接数的设置要考虑到下列几个因素:

  • 最小连接数

是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费。

  • 最大连接数

是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。

  • 最小连接数与最大连接数差距

最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。

不过,这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放

二:HikariCP连接池

1:简单使用

spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&autoReconnect=true&characterEncoding=utf8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: bfXa4Pt2lUUScy8jakXf# 指定为HikariDataSourcetype: com.zaxxer.hikari.HikariDataSource# hikari连接池配置hikari:#连接池名pool-name: HikariCP#最小空闲连接数minimum-idle: 5# 空闲连接存活最大时间,默认10分钟idle-timeout: 600000# 连接池最大连接数,默认是10maximum-pool-size: 10# 此属性控制从池返回的连接的默认自动提交行为,默认值:trueauto-commit: true# 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟max-lifetime: 1800000# 数据库连接超时时间,默认30秒connection-timeout: 30000# 连接测试queryconnection-test-query: SELECT 1

2:进一步理解

2.1:是SpringBoot2.x默认连接池

从SpringBoot自动初始化配置 和 默认的数据源 两个角度理解

SpringBoot自动初始化配置

在这里插入图片描述

然后可以找到HikariCP数据源的配置

在这里插入图片描述

可以发现,为了支持动态更新配置(基于MXBean),这里还设计了一层HikariConfigMXBean接口

为什么说是默认的数据源呢

  1. springboot-starter-jdbc中默认加载了Hikari

在这里插入图片描述

  1. 在配置初始化或者加载时都是第一个被加载的
private static <T extends DataSource> MappedDataSourceProperties<T> lookupPooled(ClassLoader classLoader,Class<T> type) {MappedDataSourceProperties<T> result = null;result = lookup(classLoader, type, result, "com.zaxxer.hikari.HikariDataSource",HikariDataSourceProperties::new);result = lookup(classLoader, type, result, "org.apache.tomcat.jdbc.pool.DataSource",TomcatPoolDataSourceProperties::new);result = lookup(classLoader, type, result, "org.apache.commons.dbcp2.BasicDataSource",MappedDbcp2DataSource::new);result = lookup(classLoader, type, result, "oracle.ucp.jdbc.PoolDataSourceImpl",OraclePoolDataSourceProperties::new, "oracle.jdbc.OracleConnection");return result;
}
2.2:为什么会成为默认连接池
  • 字节码精简 :优化代码,直到编译后的字节码最少,这样,CPU缓存可以加载更多的程序代码;
  • 优化代理和拦截器:减少代码,例如HikariCP的Statement proxy只有100行代码,只有BoneCP的十分之一;
  • 自定义数组类型(FastStatementList)代替ArrayList:避免每次get()调用都要进行range check,避免调用remove()时的从头到尾的扫描;
  • 自定义集合类型(ConcurrentBag):提高并发读写的效率;
  • 其它:针对BoneCP缺陷的优化,比如对于耗时超过一个CPU时间片的方法调用的研究等

三: 集成数据库Druid连接池

Druid连接池是阿里巴巴开源的数据库连接池项目。Druid连接池为监控而生,内置强大的监控功能,监控特性不影响性能。

功能强大,能防SQL注入,内置Loging能诊断Hack应用行为。

  • Github项目地址 https://github.com/alibaba/druid
  • 文档 https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
  • 下载 http://repo1.maven.org/maven2/com/alibaba/druid/
  • 监控DEMO http://120.26.192.168/druid/index.html

在这里插入图片描述

1:简单使用

<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.9</version>
</dependency>
spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&autoReconnect=true&characterEncoding=utf8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: bfXa4Pt2lUUScy8jakXf# Druid datasourcetype: com.alibaba.druid.pool.DruidDataSourcedruid:# 初始化大小initial-size: 5# 最小连接数min-idle: 10# 最大连接数max-active: 20# 获取连接时的最大等待时间max-wait: 60000# 一个连接在池中最小生存的时间,单位是毫秒min-evictable-idle-time-millis: 300000# 多久才进行一次检测需要关闭的空闲连接,单位是毫秒time-between-eviction-runs-millis: 60000# 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计filters: stat,wall# 检测连接是否有效的 SQL语句,为空时以下三个配置均无效validation-query: SELECT 1# 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能test-on-borrow: true# 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能test-on-return: true# 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能test-while-idle: true# 是否开启 StatViewServletstat-view-servlet:enabled: true# 访问监控页面 白名单,默认127.0.0.1allow: 127.0.0.1login-username: adminlogin-password: admin# FilterStatfilter:stat:# 是否开启 FilterStat,默认trueenabled: true# 是否开启 慢SQL 记录,默认falselog-slow-sql: true# 慢 SQL 的标准,默认 3000,单位:毫秒slow-sql-millis: 5000# 合并多个连接池的监控数据,默认falsemerge-sql: false

2:进一步理解

2.1:更多功能

Druid连接池最初就是为监控系统采集jdbc运行信息而生的,它内置了StatFilter 功能,能采集非常完备的连接池执行信息Druid连接池内置了能和Spring/Servlet关联监控的实现,使得监控Web应用特别方便Druid连接池内置了一个监控页面,提供了非常完备的监控信息,可以快速诊断系统的瓶颈

监控信息采集的StatFilter

Druid连接池的监控信息主要是通过StatFilter 采集的,采集的信息非常全面,包括SQL执行、并发、慢查、执行时间区间分布等。

  • 监控不影响性能

Druid增加StatFilter之后,能采集大量统计信息,同时对性能基本没有影响。

StatFilter对CPU和内存的消耗都极小,对系统的影响可以忽略不计。

监控不影响性能是Druid连接池的重要特性。

  • SQL参数化合并监控

实际业务中,如果SQL不是走PreparedStatement,SQL没有参数化,这时SQL需要参数化合并监控才能真实反映业务情况。

如下SQL:

select * from t where id = 1
select * from t where id = 2
select * from t where id = 3

参数化后:

select * from t where id = ?

参数化合并监控是基于SQL Parser语法解析实现的,是Druid连接池独一无二的功能。

  • 执行次数、返回行数、更新行数和并发监控

StatFilter能采集到每个SQL的执行次数、返回行数总和、更新行数总和、执行中次数和和最大并发。

并发监控的统计是在SQL执行开始对计数器加一,结束后对计数器减一实现的。

可以采集到每个SQL的当前并发和采集期间的最大并发。

  • 慢查监控

缺省执行耗时超过3秒的被认为是慢查,统计项中有包括每个SQL的最后发生的慢查的耗时和发生时的参数。

  • Exception监控

如果SQL执行时抛出了Exception,SQL统计项上会Exception有最后的发生时间、堆栈和Message,根据这些信息可以很容易定位错误原因

诊断支持

Druid连接池内置了LogFilter,将Connection/Statement/ResultSet相关操作的日志输出

可以用于诊断系统问题,也可以用于Hack一个不熟悉的系统。

LogFilter可以输出连接申请/释放,事务提交回滚,Statement的Create/Prepare/Execute/Close

ResultSet的Open/Next/Close,通过LogFilter可以详细诊断一个系统的Jdbc行为。

LogFilter有Log4j、Log4j2、Slf4j、CommsLog等实现

防止SQL注入

SQL注入攻击是黑客对数据库进行攻击的常用手段,Druid连接池内置了WallFilter 提供防SQL注入功能,在不影响性能的同时防御SQL注入攻击。

  • 基于语意的防SQL注入

Druid连接池内置了一个功能完备的SQL Parser,能够完整解析mysql、sql server、oracle、postgresql的语法

通过语意分析能够精确识别SQL注入攻击。

  • 极低的漏报率和误报率

基于SQL语意分析,大量应用和反馈,使得Druid的防SQL注入拥有极低的漏报率和误报率。

  • 防注入对性能影响极小

内置参数化后的Cache、高性能手写的Parser,使得打开防SQL注入对应用的性能基本不受影响

2.2:如何评价阿里的Druid连接池

客观的来说,阿里Druid只能说是中文开源中功能全且广泛的连接池为基础的监控组件

但是(仅从连接池的角度)在生态,维护性,开源规范性,综合性能等方面和HikariCP比还是有很大差距

功能上

首先,仅从功能上看,Druid并不是一个存粹的连接池,它还承载了监控,诊断,安全的功能。

从产品的角度看,all in one 也是有代价的,如果我只期望使用连接池的功能,其它的功能对于使用者来说就是鸡肋;

而我们没有看到其长期架构设计(比如插拔式架构,分包设计等), 大概率是当时Druid这种开源的驱动方式并不是一个完善规范的开源软件开发方式

如果你仅仅从功能上比较,就已经输了,因为这种比较根本不在一个维度上;

在这里插入图片描述

维护

文档的规范性,发包规范性,bug修复,生态构建等方面国产开源在那时(当下及未来一段时间)还有很长的路要走。

来看看相关Isusse,2k多个issues哈,没有专职维护

在这里插入图片描述


http://www.ppmy.cn/news/1568437.html

相关文章

蓝桥云客 三羊献瑞

三羊献瑞 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 观察下面的加法算式&#xff1a; 祥 瑞 生 辉 三 羊 献 瑞 -------------------三 羊 生 瑞 气其中&#xff0c;相同的汉字代表相同的数字&#xff0c;…

AI Agent的安全实践:权限控制与数据保护

在前面的文章中&#xff0c;我们讨论了 AI Agent 的各个功能模块。今天&#xff0c;我想聊聊一个经常被忽视但极其重要的话题&#xff1a;安全性。说实话&#xff0c;我在这方面也吃过亏&#xff0c;希望通过分享我的经验&#xff0c;帮大家少走一些弯路。 从一个安全事故说起…

软件测试丨从自动化软件测试到自主测试,还差几步?

在当今万物互联、信息爆炸的时代&#xff0c;软件测试的角色显得越发重要。作为软件开发生命周期&#xff08;SDLC&#xff09;中的关键环节&#xff0c;测试不仅仅是保障软件质量的工具&#xff0c;更是推动产品迭代的助推器。随着自动化测试技术的崛起&#xff0c;测试开发变…

PDF2WORD万能方法,如何控制Adobe dc pro,自动实现PDF转word

如何用JavaScript控制Adobe DC Pro来自动实现PDF转Word。首先&#xff0c;我需要考虑Adobe DC Pro是否有公开的API或者扩展接口。我记得Adobe Acrobat Pro DC支持JavaScript&#xff0c;但主要是用于表单处理和文档操作&#xff0c;比如Acrobat JavaScript。不过&#xff0c;自…

项目测试之Postman

文章目录 基础实战进行批量测试并输出报告 基础 实战 进行批量测试并输出报告 参考&#xff1a; https://blog.csdn.net/tyh_keephunger/article/details/109205191 概述 Newman是什么&#xff1f;Newman是Postman的命令行工具&#xff0c;用于执行接口测试集合。操作过程…

14-6-2C++STL的list

(一&#xff09;list对象的带参数构造 1.list&#xff08;elem);//构造函数将n个elem拷贝给本身 #include <iostream> #include <list> using namespace std; int main() { list<int> lst(3,7); list<int>::iterator it; for(itlst.begi…

二叉树的最大深度(遍历思想+分解思想)

Problem: 104. 二叉树的最大深度 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(实则二叉树的先序遍历) 1.欲望求出最大的深度&#xff0c;先可以记录一个变量res&#xff0c;同时记录每次当前节点所在的层数depth 2.在递的过程中&#xff0c;每次递一层&#xff0…

Mac m1,m2,m3芯片使用nvm安装node14报错

使用nvm安装了node 12/16/18都没有问题&#xff0c;到14就报错了。第一次看到这个报错有点懵&#xff0c;查询资料发现是Mac芯片的问题。 Issue上提供了两个方案&#xff1a; 1、为了在arm64的Mac上安装node 14&#xff0c;需要使用Rosseta&#xff0c;可以通过以下命令安装 …