1 概述

应用程序建立与数据库的连接其实是一项开销很大的工作,其中涉及网络连接的建立、会话的建立、数据库端与应用程序的适配等诸多操作。因此,大部分情况下我们会选择将数据库连接进行池化管理。

连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。

同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。此外,大部分数据库连接池还提供了不同SQL Dialect的适配、查询缓存、性能监控、插件扩展等特性,进一步丰富了数据库连接池的功能。

2 整体架构

HikariCP与Druid同属于第二代连接池,但前者代码与结构极其精简。只需要从其核心类HikariPool入手,就可以把整体架构梳理出来。HikariCP启动时首先根据用户配置创建HikariConfig类,然后通过JDBC驱动加载DataSource,加载完成后根据配置初始化连接池,然后创建连接。连接的创建回收都是通过独立的线程池来异步处理的,同时还是用一个定时线程池来处理连接泄漏和数据监控统计的任务。所有的连接以PoolEntry的形式存储在ConcurrentBag中,每个PoolEntry对应一个被HikariCP代理的JDBC连接。

3 连接管理

3.1 申请连接

HikariPool负责对资源连接进行管理,而ConcurrentBag则是作为物理连接的共享资源站,PoolEntry则是对物理连接的一对一封装。PoolEntry通过borrow方法从bag中取出,之后通过PoolEntry.createProxyConnection调用工厂类生成HikariProxyConnection返回。

hikaricp_getconnection

3.2 归还连接

HikariProxyConnection调用close方法时实际上通过代理调用了PooleEntry的recycle方法,之后通过HikariPool调用了ConcurrentBag的requite放回。(poolEntry通过borrow从bag中取出,再通过requite放回。资源成功回收)。

hikaricp_close.png

3.3 创建连接

HikariCP中通过独立的线程池addConnectionExecutor进行新连接的生成,连接生成方法为PoolEntryCreator。物理链接的生成只由PoolBase的newConnection()实现,之后封装成PoolEntry,通过Bag的add方法加入ConcurrentBag。当ConcurrentBag存在等待线程,或者有连接被关闭时,会触发IBagItemListener的addBagItem(wait)方法,调用PoolEntryCreator进行新连接的生成。

hikaricp_createPoolEntry.png

3.4 回收连接

closeConnectionExecutor关闭连接后,会调用fillPool()方法对连接池进行连接填充。同时HikariPool提供evictConnection(Connection)方法对物理连接进行手动关闭。虽然连接池提供了直接回收连接的接口,但对于开发者来说一般不需要显示调用,只有连接本身状态异常或者连接池shutdown的时候才需要回收连接。

hikaricp_evict.png

4 数据结构

4.1 ConcurrentBag

ConcurrentBag内部同时使用了ThreadLocal和CopyOnWriteArrayList来存储元素,其中CopyOnWriteArrayList是线程共享的。ConcurrentBag采用了queue-stealing的机制获取元素:首先尝试从ThreadLocal中获取属于当前线程的元素来避免锁竞争,如果没有可用元素则扫描公共集合、再次从共享的CopyOnWriteArrayList中获取。(ThreadLocal列表中没有被使用的items在借用线程没有属于自己的时候,是可以被“窃取”的)

ThreadLocal和CopyOnWriteArrayList在ConcurrentBag中都是成员变量,线程间不共享,避免了伪共享(false sharing)的发生。

 //负责存放ConcurrentBag中全部用于出借的资源 private final CopyOnWriteArrayList sharedList; //是否使用弱引用的标志位 private final boolean weakThreadLocals; //用于加速线程本地化资源访问 private final ThreadLocal> threadList; //任务窃取时的事件监听器 private final IBagStateListener listener; //等待资源交接的线程计数器 private final AtomicInteger waiters; private volatile boolean closed; //用于存在资源等待线程时的第一手资源交接 private final SynchronousQueue handoffQueue;

ConcurrentBag的添加和删除方法比较简单,直接对sharedList进行添加操作,同时尝试通过handoffQueue交接新添加的Connection;而删除时则先CAS修改Connection的状态,如果操作成功才会移除。

public void add(final T bagEntry){ if (closed) { LOGGER.info("ConcurrentBag has been closed, ignoring add()"); throw new IllegalStateException("ConcurrentBag has been closed, ignoring add()"); } sharedList.add(bagEntry);//新添加的资源优先放入CopyOnWriteArrayList // 自旋等待直到将资源交到某个等待线程后才返回(SynchronousQueue) while (waiters.get() > 0 && !handoffQueue.offer(bagEntry)) { yield(); }}public boolean remove(final T bagEntry){// 如果资源正在使用且无法进行状态切换,则返回失败 if (!bagEntry.compareAndSet(STATE_IN_USE, STATE_REMOVED) && !bagEntry.compareAndSet(STATE_RESERVED, STATE_REMOVED) && !closed) { LOGGER.warn("Attempt to remove an object from the bag that was not borrowed or reserved: {}

# 再次尝试 连接失败_新一代高效连接池HikariCP设计简要分析相关推荐

  1. Win7 easy connect 提示:选路连接失败,可能当前连接网络异常,请稍后重试

    环境: Win7 旗舰版 easy connect 问题描述: 打开easy connect 提示:选路连接失败,可能当前连接网络异常,请稍后重试,无法连接 解决方案: 1.重新安装easy conn ...

  2. 性能优化-高效内存池的设计与实现

    原文地址: 高效内存池的设计与实现 关注公众号[高性能架构探索],也可以后台回复[pdf],获取计算机必备经典书籍 大家好,我是雨乐! 在之前的文章中,我们分析了glibc内存管理相关的内容,里面的是 ...

  3. c# 再次尝试 连接失败_[图]连接USB或者SD卡的PC将阻止升级Windows 10 May 2019功能更新...

    如果设备在连接外部USB设备或者读卡器的时候,计算机将会阻止升级Windows 10 May 2019(Version 1903)功能更新.在4月24日发布的技术咨询中,微软解释称当连接外部USB设备 ...

  4. c# 再次尝试 连接失败_手机投屏电视连接不上怎么回事?

    现在的智能设备功能越来越多了,以家庭用户为单位,很多设备功能都是可以共享的.但基于用户对使用设备的不了解,在使用过程中会遇到很多解决不了的问题.本期文章就说说"手机投屏电视"连接不 ...

  5. cassandra本地连接失败_本地网络发现失败的解决方法连接到OS X中的服务器的问题 | MOS86...

    本地联网通常在Mac上完美无缺,这就是为什么某些用户可能会遇到OS X优胜美地的一些最恶化的问题与网络连接有关.其中一些可能涉及更广泛的连接和Wi-Fi功能问题,以及其他可能影响一般LAN网络功能的能 ...

  6. 显示连接失败_技术丨外接显示器障碍的诊断方法

    连接显示器时,有时会遇到显示器连接失败的情况,那我们该怎么找到问题所在呢?本期视频将为大家介绍几个解决外接显示器故障的方法,一起来看看吧! 检查设备有无物理损坏 查看设备是否存在任何物理损坏.确保视频 ...

  7. mongodb连接失败_深入浅出mongodb(一)

    我年轻时注意到,我每做十件事有九件不成功,于是我就十倍地去努力干下去.--萧伯纳 前言 在大数据的驱使下,我们要实现数据持久化存储,数据共享,数据集中管理数据库是不二之选,小编在这里要阐述的是 mon ...

  8. 建立安全连接失败_安全失败

    建立安全连接失败 上周,我参加了有关可伸缩敏捷框架SAFe的演示 . 我之前已经阅读过有关它的内容,但这是对该主题的更广泛的介绍. 这将是成功的. 当我谈论scrum为什么成功地跨越了开发人员世界到业 ...

  9. 乐播投屏总是自动断开_人人视频投屏连接失败_不能投屏电视解决办法_3DM手游...

    不少小伙伴在使用人人视频APP看视频的时候,都会用到其中的投屏功能.但是有时投屏的过程中会出现连接失败,不能投屏的情况,这该怎么办呢?下面我们一起来看看人人视频无法投屏电视的解决办法. 人人视频无法投 ...

最新文章

  1. CORS漏洞利用检测和利用方式
  2. 使用HTML5监測站点性能
  3. 破4!《我想进大厂》之Java基础夺命连环16问
  4. [原]Java 正则 多子串 匹配 替换
  5. ubuntu创建新用户名和密码以及查看删除用户
  6. Windows 窗体启动和关闭的事件顺序
  7. linux默认开启sudo_Sudo漏洞允许非特权Linux和macOS用户以root身份运行命令
  8. 【邀请函】2021钉钉宜搭·线上沙龙,邀您云上相见!
  9. mysql adminer 导入csv_mysql导入csv的4种报错的解决方法
  10. php 添加音乐,PHP网站插入音乐
  11. macOS 10.11.* 安装scrapy
  12. 如何查看Laravel版本号的三种方法
  13. dp线和hdmi区别_HDMI铜线与光纤线有啥区别?为什么铜线传播速度更快?看完涨知识...
  14. 苹果拟明年Q1推出配有mini-LED显示屏的27英寸iMac
  15. js 取get过来的数据
  16. 最便宜、最快和最可靠不可兼得
  17. 企业组织形态及财务报表
  18. Oracle 分析函数row_number() over (partition by order by )
  19. ubuntu 20.04 firefox视频打不开问题
  20. 2020-4-18 深度学习笔记20 - 深度生成模型 2 (深度信念网络DBN,深度玻尔兹曼机DBM)

热门文章

  1. 使用$.post和action或servlet交互 URL出现 http://localhost:8080/../[object%20Object] 错误的问题解决
  2. 解决为什么已经设置了request.setCharacterEncoding(“utf-8“);POST请求仍然乱码的问题
  3. 我什么时候应该真正使用noexcept?
  4. 如何在python中检查文件大小?
  5. php complex,PHP復雜的基於角色的訪問控制列表
  6. ros开发增加clion常用模板及初始化配置(五)
  7. maven构建ssm工程
  8. L1-02 聪明的高斯 (5 分)
  9. 案例-三角形(CSS3)
  10. 实验7-3-4 字符串替换 (15 分)