【Spring Boot 应用开发】-04-01 自动配置-数据源-连接池

资源关闭

还记得上一节中的这段代码么?

try {if (resultSet != null) resultSet.close();if (preparedStatement != null) preparedStatement.close();if (connection != null) connection.close();
} catch (SQLException e) {e.printStackTrace();
}

这是我们在查询完毕之后,关闭和释放资源。我们都知道数据库可接受的链接是有限的,如果不进行关闭,那么可用连接就会被耗尽,这样新的访问就无法被处理了。更全面的说明如下:

为什么必须关闭数据库连接

  1. 资源管理

    • 解释:数据库连接是有限的资源。每个连接都需要占用数据库服务器的内存、线程和其他系统资源。如果不关闭连接,这些资源将一直被占用,可能导致资源耗尽。
    • 后果:当数据库连接耗尽时,新的连接请求将被拒绝,应用程序将无法继续正常工作。
  2. 性能优化

    • 解释:频繁地建立和关闭连接会导致性能下降。每次建立连接都需要进行上述的多个步骤,耗时较长。
    • 后果:这会降低应用程序的响应速度和吞吐量。
  3. 避免资源泄漏

    • 解释:如果连接没有被正确关闭,它们会一直保持打开状态,导致资源泄漏。
    • 后果:长时间运行的应用程序可能会因为资源泄漏而变得不稳定,甚至崩溃。
  4. 事务管理

    • 解释:未关闭的连接可能会导致事务管理问题。如果连接没有正确关闭,事务可能不会被正确提交或回滚。
    • 后果:这可能导致数据不一致和其他事务相关的问题。
  5. 安全性

    • 解释:未关闭的连接可能会被恶意利用,导致安全风险。
    • 后果:攻击者可能利用未关闭的连接进行未经授权的操作,导致数据泄露或其他安全问题。

上面出现了多次“泄露”这个词,为什么用这个词呢?因为资源被耗尽这种现象类似于水装满了,从容器中意外流出的场景,就像下面这个图:
在这里插入图片描述

给个池子

怎么来解决这个问题呢?

解决任何问题都可以在中间加一层

数据库连接池

产生背景

在早期的数据库应用开发中,每次应用程序需要访问数据库时,都会创建一个新的数据库连接。这种做法存在以下几个问题:

  • 性能开销大:建立和关闭数据库连接是一个相对耗时的操作,频繁的连接操作会显著降低应用程序的性能。
  • 资源浪费:每次创建新的连接都会消耗系统资源,过多的连接会导致资源耗尽,影响系统的稳定性。
  • 并发控制困难:在高并发环境下,频繁创建和关闭连接会导致数据库服务器负载过高,难以有效控制并发访问。

为了解决这些问题,数据库连接池应运而生。连接池预先创建一定数量的数据库连接,并将这些连接保存在一个池中,应用程序需要访问数据库时,可以直接从连接池中获取已建立的连接,使用完毕后再将连接归还到池中,而不是关闭连接。这种方式大大提高了性能和资源利用率。

特性
  1. 连接复用:连接池中的连接可以被多个请求复用,减少了创建和关闭连接的开销。
  2. 性能优化:通过预先创建和管理连接,连接池能够显著提高数据库访问的性能。
  3. 资源管理:连接池能够有效管理数据库连接的生命周期,避免资源浪费。
  4. 并发控制:通过配置连接池的最大连接数等参数,可以有效控制并发访问的数量,防止数据库服务器过载。
  5. 简化开发:开发者无需手动管理数据库连接的生命周期,由连接池自动处理,降低了代码复杂度。
场景
  • Web应用:在Web应用中,数据库连接池可以显著提高响应速度和并发处理能力。
  • 分布式系统:在分布式系统中,连接池能够有效管理多个节点之间的数据库连接,提高系统的整体性能和稳定性。
  • 大数据处理:在大数据处理场景中,连接池能够有效管理大量的数据库连接,确保数据处理的高效性和稳定性。
常见的高性能数据库连接池框架
  1. HikariCP

    • 特点:HikariCP是一个高性能的JDBC连接池,设计目标是成为最快的JDBC连接池。
    • 优点:低延迟、高性能、易于配置。
    • 适用场景:适用于需要高性能和低延迟的应用场景。
  2. C3P0

    • 特点:C3P0是一个开源的JDBC连接池,支持JNDI绑定和JMX管理。
    • 优点:功能丰富、支持多种数据库。
    • 适用场景:适用于需要多种数据库支持和复杂配置的应用场景。
  3. Druid

    • 特点:Druid是一个阿里巴巴开源的数据库连接池,提供了强大的监控和扩展功能。
    • 优点:监控功能强大、支持多种数据库、易于扩展。
    • 适用场景:适用于需要监控和扩展功能的应用场景。
  4. Tomcat JDBC Pool

    • 特点:Tomcat JDBC Pool是Apache Tomcat自带的连接池,轻量级且易于集成。
    • 优点:轻量级、易于集成。
    • 适用场景:适用于轻量级应用和嵌入式应用。
代码示例

以下是一个使用HikariCP作为数据库连接池的Spring Boot配置示例:

# application.yaml
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: secretdriver-class-name: com.mysql.cj.jdbc.Driverhikari:maximum-pool-size: 10 # 最大连接数minimum-idle: 5       # 最小空闲连接数idle-timeout: 30000   # 空闲连接超时时间(毫秒)connection-timeout: 20000 # 获取连接超时时间(毫秒)

Spring Boot 2.0之后,只要你依赖了spring-boot-starter-jdbc自动配置类,那么在启动之后,会默认使用连接池,且默认连接池就是hikari,即使不显示的配置hikari参数,那么也会使用默认的参数

Hikari数据库连接池的实现原理

1.核心组件
  • HikariDataSource:作为应用程序与 HikariCP 交互的主要接口,实现了 javax.sql.DataSource 接口。
  • PoolBase:负责管理连接池的基本功能,如创建新连接、维护连接状态等。
  • HikariPool:继承自 PoolBase,是连接池的核心实现类,负责连接的分配、回收以及健康检查。
  • ConnectionProxy:代理实际的 JDBC 连接对象,用于拦截和处理连接的操作,确保连接在使用完毕后能正确返回到池中。
2.初始化过程
  • 当创建 HikariDataSource 实例时,会根据配置参数初始化 HikariCP 的内部状态。
  • 调用 initializePool() 方法启动后台线程(如果启用了连接测试),并预填充一定数量的空闲连接到池中。
3. 获取连接
  • 应用程序调用 getConnection() 方法请求连接。
  • 如果池中有可用连接,则直接返回给调用者;否则,尝试创建新的物理连接或等待其他线程归还连接。
  • 使用完连接后,必须显式地关闭它,这实际上只是将连接归还给池而不是真正关闭。
4. 连接回收
  • 当连接被归还给池时,会先进行健康检查(可选)。
  • 如果连接仍然有效,则将其标记为可用;若无效则销毁该连接并在需要时补充新的连接。
5. 空闲连接清理
  • 定期扫描池中的空闲连接,并根据配置规则移除那些长时间未使用的连接以节省资源。

6.源码分析
// HikariDataSource.java
public class HikariDataSource implements DataSource {private final HikariPool pool;public HikariDataSource() {this.pool = new HikariPool(this);}@Overridepublic Connection getConnection() throws SQLException {return pool.getConnection();}
}// HikariPool.java (部分代码)
public class HikariPool extends PoolBase {private final ConcurrentBag<PoolEntry> connectionBag;// 获取连接的方法public Connection getConnection() throws SQLException {final long startTime = System.nanoTime();final TimeTracker tracker = new TimeTracker(startTime);try {// 尝试从池中获取连接PoolEntry entry = connectionBag.borrow(timeout, MILLISECONDS);if (entry == null) {throw new SQLException("Timeout after " + timeout + "ms waiting for connection.");}// 返回代理后的连接return entry.getConnection();} catch (InterruptedException e) {Thread.currentThread().interrupt();throw new SQLException("Interrupted while waiting for a connection.", e);}}
}

以上代码片段展示了 HikariCP 中如何通过 HikariDataSourceHikariPool 类来管理数据库连接的获取与释放。实际源码更为复杂,包含了更多细节处理逻辑,例如连接超时、异常处理等。这里不做过多阐述,有兴趣的朋友可以私聊共学。


7.获取连接的时序图
应用程序 HikariDataSource HikariPool ConcurrentBag 数据库 Connection getConnection() getConnection() borrow() 返回PoolEntry 返回代理后的Connection 创建新连接 返回新连接 添加新连接到池 返回PoolEntry 返回代理后的Connection alt [池中有可用连接] [池中无可用连接] 使用连接 close() 归还连接 返回PoolEntry到池中 应用程序 HikariDataSource HikariPool ConcurrentBag 数据库 Connection

为什么jdbc中不直接给池子?

那很多童鞋会问了,为啥JDBC不直接提供一个连接池呢?搞这么麻烦,我要一站式服务。其实这是有原因的。如下:

1. 灵活性和可扩展性

  • 不同需求:不同的应用程序对连接池的需求可能不同。一些应用程序可能需要高性能的连接池,而另一些可能需要更复杂的连接管理功能。内置连接池可能会限制这种灵活性。
  • 第三方库:通过将连接池功能分离到第三方库中,JDBC允许开发者根据具体需求选择合适的连接池实现。例如,HikariCP、C3P0、Druid等都是高性能的连接池库,开发者可以根据自己的需求选择最适合的库。

2. 标准与实现分离

  • 标准定义:JDBC作为标准API,主要定义了与数据库交互的基本接口和方法。连接池功能属于更高层次的实现细节,不适合直接包含在标准API中。
  • 实现多样性:通过将连接池功能分离,不同的数据库厂商和第三方开发者可以提供多种实现,满足不同场景的需求。这种多样性有助于推动技术的发展和创新。

3. 性能优化

  • 定制化:不同的应用场景可能需要不同的性能优化策略。内置连接池可能无法提供针对特定场景的最佳优化,而第三方库可以根据具体需求进行定制和优化。
  • 轻量级:JDBC作为基础API,保持轻量级有助于提高整体性能。内置连接池可能会增加不必要的开销,影响JDBC的性能表现。

4. 复杂性管理

  • 简化核心:JDBC的核心功能是提供数据库访问的基本接口和方法。如果将连接池功能内置,会增加JDBC的复杂性,使得API更加庞大和难以维护。
  • 模块化设计:通过模块化设计,JDBC保持了核心功能的简洁性,而将连接池等功能交由第三方库实现,使得整个生态系统更加灵活和高效。

5. 历史原因

  • 早期设计:JDBC的设计始于1997年,当时连接池技术尚未成熟。随着时间的推移,连接池技术得到了快速发展,形成了多种成熟的第三方库。
  • 社区贡献:连接池功能主要由社区贡献和维护,这种方式促进了技术的快速迭代和优化。

6. 兼容性

  • 跨平台:JDBC作为跨平台的标准API,内置连接池可能会导致兼容性问题。第三方库可以针对不同的平台和环境进行优化,确保更好的兼容性。
  • 版本管理:通过将连接池功能分离,可以独立管理连接池库的版本,避免与JDBC版本之间的冲突和兼容性问题。

7. 安全性

  • 隔离性:将连接池功能分离可以提高安全性,避免核心API中引入不必要的复杂性和潜在的安全漏洞。
  • 模块化安全:第三方库可以独立进行安全审计和更新,确保连接池功能的安全性。

JDBC不直接内置数据库连接池遵循的核心原则是:让你的模块遵循单一职责原则,这样可以让整个模块的安全性、扩展性等更好,要小而精,不要大而全。这也是我们设计模块可以借鉴的地方。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/1623.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BUUCTF:misc刷题记录4(会持续更新的)

目录 爱因斯坦 ningen 做题总结&#xff1a; 爱因斯坦 下载解压后&#xff0c;得到一张图片。 老套路&#xff0c;还是先查看一下图片基本属性。只看到这串信息&#xff0c;不知道有啥用。 然后用010进行查看 发现图片里面隐藏了一个压缩包&#xff0c;压缩包里面有个flag.t…

Open FPV VTX开源之嵌入式OSD配置

Open FPV VTX开源之嵌入式OSD配置 1. 源由2. 安装3. 配置步骤一&#xff1a;备份/etc/telemetry.conf步骤二&#xff1a;修改/etc/telemetry.conf步骤三&#xff1a;配置时区步骤四&#xff1a;重启摄像头 4. 实测5. 参考资料 1. 源由 穿越机模拟图传延迟通常在10ms左右。 最…

JavaScript动态渲染页面爬取之Splash

Splash是一个 JavaScript渲染服务,是一个含有 HTTP API的轻量级浏览器,它还对接了 Python 中的 Twisted 库和 OT库。利用它&#xff0c;同样可以爬取动态渲染的页面。 功能介绍 利用 Splash&#xff0c;可以实现如下功能&#xff1a; 异步处理多个网页的渲染过程:获取渲染后…

HTTP详解——HTTP基础

HTTP 基本概念 HTTP 是超文本传输协议 (HyperText Transfer Protocol) 超文本传输协议(HyperText Transfer Protocol) HTTP 是一个在计算机世界里专门在 两点 之间 传输 文字、图片、音视频等 超文本 数据的 约定和规范 1. 协议 约定和规范 2. 传输 两点之间传输&#xf…

云服务信息安全管理体系认证,守护云端安全

在数据驱动的时代&#xff0c;云计算已成为企业业务的超级引擎&#xff0c;推动着企业飞速发展。然而&#xff0c;随着云计算的广泛应用&#xff0c;信息安全问题也日益凸显&#xff0c;如同暗流涌动下的礁石&#xff0c;时刻威胁着企业的航行安全。这时&#xff0c;云服务信息…

nacos环境搭建以及SpringCloudAlibaba脚手架启动环境映射开发程序

1&#xff1a;下载nacos 地址&#xff1a;https://github.com/alibaba/nacos/tags 2:选择server的zip包下载 3:启动mysql服务&#xff0c;新建数据库&#xff1a;nacos_yh 4&#xff1a;解压下载的nacos_server 进入conf目录 5&#xff1a;mysql运行sql脚本变得到下面的表 6&a…

stable diffusion 量化学习笔记

文章目录 一、一些tensorRT背景及使用介绍1&#xff09;深度学习介绍2&#xff09;TensorRT优化策略介绍3&#xff09;TensorRT基础使用流程4&#xff09;dynamic shape 模式5&#xff09;TensorRT模型转换 二、TensorRT转onnx模型1&#xff09;onnx介绍2&#xff09;背景知识&…

设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析

访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为设计模式&#xff0c;它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离&#xff0c;使得可以独立地变化那些保存在复杂对象结构中的元素的操作。 假设我们有一个复杂的对…

C++中引用参数与指针参数的区别与联系详解

在C++中,函数参数可以通过值传递、引用传递和指针传递。虽然指针传递在C和C++中都非常常见,但C++引入了引用类型,使得引用传递变得更加直接和易用。本文将详细介绍函数中引用参数和指针参数的区别与联系,并通过C++语言代码示例加以说明。 一、基本概念 值传递(Pass by Val…

初识JVM HotSopt 的发展历程

目录 导学 目前企业对程序员的基本要求 面向的对象 实战 学习目标 JVM 是什么 JVM 的三大核心功能 各大 JVM look 看一下虚拟机 HotSopt 的发展历程 总结 导学 目前企业对程序员的基本要求 面向的对象 实战 学习目标 JVM 是什么 JVM 的三大核心功能 即时编译 主要是…

html中鼠标位置信息

pageX&#xff1a;鼠标距离页面的最左边的距离&#xff0c;包括滚动条的长度。clientX&#xff1a;鼠标距离浏览器视口的左距离&#xff0c;不包括滚动条。offsetX&#xff1a;鼠标到事件源左边的距离。movementX&#xff1a;鼠标这次触发的事件的位置相对于上一次触发事件的位…

RabbitMQ 高可用方案:原理、构建与运维全解析

文章目录 前言&#xff1a;1 集群方案的原理2 RabbitMQ高可用集群相关概念2.1 设计集群的目的2.2 集群配置方式2.3 节点类型 3 集群架构3.1 为什么使用集群3.2 集群的特点3.3 集群异常处理3.4 普通集群模式3.5 镜像集群模式 前言&#xff1a; 在实际生产中&#xff0c;RabbitM…

【容器逃逸实践】挂载/dev方法

0、前置知识 怎么在容器里面执行命令&#xff0c; 有几种方法 # 不进入容器&#xff0c;创建并启动一个新的容器 $ docker run -itd --name ubuntu-test ubuntu /bin/bash # 进入容器&#xff0c;创建并启动一个新的容器 $ docker run -itd --name ubuntu-test ubuntu /bin…

linux: 文本编辑器vim

文本编辑器 vi的工作模式 (vim和vi一致) 进入vim的方法 方法一:输入 vim 文件名 此时左下角有 "文件名" 文件行数,字符数量 方法一: 输入 vim 新文件名 此时新建了一个文件并进入vim,左下角有 "文件名"[New File] 灰色的长方形就是光标,输入文字,左下…

Python爬虫-汽车之家各车系周销量榜数据

前言 本文是该专栏的第43篇,后面会持续分享python爬虫干货知识,记得关注。 在本专栏之前,笔者在文章《Python爬虫-汽车之家各车系月销量榜数据》中,有详细介绍,如何爬取“各车系车型的月销量榜单数据”的方法以及完整代码教学教程。 而本文,笔者同样以汽车之家平台为例,…

Python----Python高级(函数基础,形参和实参,参数传递,全局变量和局部变量,匿名函数,递归函数,eval()函数,LEGB规则)

一、函数基础 1.1、函数的用法和底层分析 函数是可重用的程序代码块。 函数的作用&#xff0c;不仅可以实现代码的复用&#xff0c;更能实现代码的一致性。一致性指的是&#xff0c;只要修改函数的代码&#xff0c;则所有调用该函数的地方都能得到体现。 在编写函数时&#xf…

欧拉路径算法

欧拉图&#xff1a; 对于应该连通图G&#xff0c;有&#xff1a; 1欧拉路径&#xff1a;一条路径&#xff0c;它能够不重复地遍历完所有的边&#xff0c;这个性质很像不重复地一笔画完所有边&#xff0c;所以有些涉及到欧拉路径的问题叫做一笔画问题。 2欧拉回路&#xff1a…

后端技术选型 sa-token校验学习 下 结合项目学习 后端鉴权

目录 后端注册拦截器 实现对 WebMvcConfigurer 接口的类实现 静态变量 方法重写 注册 Spring Framework拦截器 Sa-Token中SaServletFilter拦截器 思考 为什么使用两个拦截器 1. Spring Framework 拦截器 2. SaServletFilter 为什么要注册两个拦截器&#xff1f; 总结 …

Angular-生命周期及钩子函数

什么是生命周期 Angular 创建和渲染组件及其子组件&#xff0c;当它们绑定的属性发生变化时检查它们&#xff0c;并在从 DOM 中移除它之前销毁它们。生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。当 Angular 使用构造函数新建一个组件或…

Microsoft

Microsoft Word目录1.目录编号与文字的间距设置2. 目录编号缩进设置 Excel函数MID&#xff08;提取字符&#xff09;CONCAT&#xff08;组合字符串&#xff09;EXACT&#xff08;比较字符串&#xff09; PowerPointwindows 11 恢复右键传统菜单 Word 目录 1.目录编号与文字的…