HikariCP连接池分析内部分享

HikariCP连接池分享

希望可以带着大家了解HikariCP连接池,并对线上问题给出解决思路和方案。然后可以自己去看一下HikariCP,个人感觉HikariCP实现的比较精巧,代码很值得一读,我这里会给出整体的设计和一些主流程,可以减少大家深入HikariCP的时间。

为什么分享HikariCP连接池?
线上问题:获取连接池失败?
结果:整个服务在一段时间不可用

引出了这些问题,是我想到的一些问题,也是我的解决问题的思路

1、什么是连接池?
2、为什么用连接池?
3、为什么用HikariCP连接池?
4、HikariCP连接池有什么特色?
5、系统怎么加载HikariCP连接池的?
6、一个获取Connection的过程是什么?
7、为什么获取连接池失败?连接池太小?怎么解决线上问题?
8、HikariCP连接池的实现原理(是怎么实现的?):
设计哲学
整体设计原理
源码

目录

  1. 什么是连接池

  2. 连接池的功能

  3. Spring Boot 加载HikariCP的流程

  4. HikariCP的设计
    设计哲学
    设计原理
    核心源码
    总结

  5. 线上问题解决思路
    1、拆分业务
    2、加大线程池
    3、扩容
    4、使用flexyPool

  6. 回顾

什么是连接池

日常生活中我们买车,都是商家预先买一批,我们去买的时候直接交钱,就可以开回来家了,而不是等着我们买一辆车,商家去制造商那里制造一辆,然后运过来。在日常开发中最常用的是Java线程池(Tomcat线程池),创建和消费线程比较耗用资源,并且耗费时间,甚至有些情况下还会带来一定的副作用。因此有了连接池组件,可以预先在池子里建几个,等需要用的时候去取或者激活,用完之后放到池子复用,避免了大量的创建和销毁代价。就我们产品而言,类似的还有Redis连接池(LettucePool),HttpClient连接池(ConnPool)等。
连接池和线程池还是有一定区别的,但是思想是相同的,(都是避免关键资源大量的重复创建和销毁)为了效率和性能。池化思想还有内存池(Netty,Kafka),对象池(单例,享元模式)。

连接池的功能

或者说如果不用连接有什么问题,使用连接池之后有什么作用;

主要问题:

  1. 大量的连接池会对服务端造成比较大的压力,甚至会造成服务器内存溢出;
  2. 创建和销毁连接是比较耗时的;
  3. 频繁的创建连接会导致JVM的临时对象比较多,GC频繁;
  4. 对于客户端而言会出现大量的TIME_WAIT的TCP状态,调优会比较麻烦;(只Redis没有使用连接池,系统的TIME_WAIT就可以达到5到6千左右);

优点

  1. 资源的复用,减少了大量的创建和销毁代价;
  2. 系统响应速度会更快;
  3. 连接管理更加可控;
  4. 对服务端的连接有个上限,防止大量连接对服务端造成影响。

Spring Boot 加载HikariCP的流程

常用的连接池有 Tomcat JDBC Pool、 Druid、HikariCP
Tomcat Pool是Spring Boot 1.5默认的连接池,之前查Link模块问题的时候还遇到过,在Spring Boot2.0之后默认使用HikariCP:
系统配置:spring.datasource.type:com.zaxxer.hikari.HikariDataSource
DataSourceAutoConfiguration
DataSourceConfiguration

 private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
		"com.zaxxer.hikari.HikariDataSource",
		"org.apache.tomcat.jdbc.pool.DataSource",
		"org.apache.commons.dbcp2.BasicDataSource" };
public static Class<? extends DataSource> findType(ClassLoader classLoader) {
	for (String name : DATA_SOURCE_TYPE_NAMES) {
		try {
			return (Class<? extends DataSource>) ClassUtils.forName(name,
					classLoader);
		}
		catch (Exception ex) {
			// Swallow and continue
		}
	}
	return null;
}
 

HikariCP的设计

HikariCP是一个快速、简单、可靠的高效能的JDBC连接池组件。

设计哲学

简单,高效是HikariCP的设计哲学,简单是代码尽量精简,配置使用尽量易于使用;HikariCP的作者拒绝了很多的功能请求;简单就是大道至简。

设计原理

常用的配置:

spring.datasource.hikari.connection-timeout
spring.datasource.hikari.idle-timeout
spring.datasource.hikari.max-lifetime
spring.datasource.hikari.maximum-pool-size
spring.datasource.hikari.minimum-idle

连接池负责连接的分配、管理和释放;主要职责:

  1. 维护一个队列存放连接
  2. 支持最小连接数,最大连接数
  3. 每个连接数有个最大生存时间(数据库有个最大的wait_time)
  4. 维护最小连接数
  5. 线程安全的给上层业务提供连接,如果达到最大连接数会阻塞线程,支持超时

如何实现?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JtyS6kxx-1601017638025)(leanote://file/getImage?fileId=5f69f1543a2b494bb3000002)]

线程模型
  • HouseKeeper
    HouseKeeper任务的线程池houseKeepingExecutorService:
 final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, threadFactory, new ThreadPoolExecutor.DiscardPolicy());
         executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
         executor.setRemoveOnCancelPolicy(true);

1, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), threadFactory, handler

  • PoolEntryCreator addConnectionExecutor
1 /*core*/, 1 /*max*/, 5 /*keepalive*/, SECONDS, new LinkedBlockingQueue<>(config.getMaximumPoolSize()), threadFactory, policy
  • anonymous closeConnectionExecutor
1 /*core*/, 1 /*max*/, 5 /*keepalive*/, SECONDS, new LinkedBlockingQueue<>(config.getMaximumPoolSize()), threadFactory, policy
获取连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t4afVTc2-1601017638031)(leanote://file/getImage?fileId=5f69e9253a2b494bb3000001)]

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于HikariCP连接池,动态密码可以通过以下步骤实现: 1. 首先,添加HikariCP和MyBatis-Plus的依赖到你的项目中。 2. 在配置文件(比如application.properties或application.yml)中配置HikariCP连接池的相关参数,比如数据库URL、用户名、初始密码等。将密码字段设置为占位符,例如:`spring.datasource.password=placeholder`. 3. 在项目启动时,通过编程方式获取到真实的密码,并将其设置到HikariCP连接池的配置中。 4. 可以使用Spring的事件机制,在应用启动时监听事件,在事件监听器中获取真实密码并设置到HikariCP连接池配置中。 下面是一个示例代码: ```java @Component public class HikariPasswordListener implements ApplicationListener<ApplicationReadyEvent> { @Autowired private HikariDataSource dataSource; @Override public void onApplicationEvent(ApplicationReadyEvent event) { // 获取真实密码的逻辑,可以从配置文件、数据库或其他安全存储中获取 String realPassword = "your_real_password"; // 设置真实密码到HikariCP连接池配置中 dataSource.setPassword(realPassword); } } ``` 在上述示例中,我们创建了一个监听器 `HikariPasswordListener`,并在应用启动时监听 `ApplicationReadyEvent` 事件。在监听器中,我们注入了 `HikariDataSource` 对象,并获取真实的密码。然后将真实密码设置到 `HikariDataSource` 对象的密码字段中。 这样,HikariCP连接池就可以使用动态密码了。注意,示例中使用了Spring的事件机制,如果你的项目没有使用Spring,可以考虑使用其他适合的方式来设置真实密码到HikariCP连接池配置中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值