聊聊Druid(二) -- 获取连接

连接池的最核心的一个功能就是连接管理。我们先来看看在druid中获取连接是怎样的一个实现过程。先来一张图对整个连接获取的过程进行描绘

连接获取与创建

输入图片说明

(右键打开新标签查看大图)

客户端通过dataSource.getConnection获取连接,连接获取的具体实现逻辑如下:

1、判断是否有Filter,如果存在通过filterChain获取连接,否则通过getConnectionDirect方法获取连接。

2、获取全局锁lock。数据源中拥有很多数据源相关的属性,而数据源又是一个高并发的环境中使用的,所以需要先获取到数据源的锁才能进行连接的获取。

3、connections数组存放存放当前数据源可用的连接,假如当前connections有可用的连接(通过poolingCount判断),就直接返回连接,递减connections中可用连接的数量

4、当connections中已经没有可用的连接时,就需要进行notEmpty条件等待,并且进行empty的唤醒。因为连接的创建是另外的线程的工作。通常是CreateConnectionThread线程负责连接的创建。

当前线程使用了一个notEmpty的条件进行等待,释放lock。
CreateConnectionThread在有足够的可用连接时是进行等待,等待条件empty的唤醒。所以当当前线程进行empty.signal时,
CreateConnectionThread从等待中被唤醒,创建连接。连接创建完后进行notEmpty的条件唤醒,然后继续进行empty的条件等待。

需要获取连接的线程被notEmpty.signal唤醒后(唤醒需要重新获取锁,有可能被其他线程获取到锁,
从而获取了刚刚生成的连接,那么线程将从头开始进行等待)从connections中获取连接。

从池中获取连接后

  • 获取之前
  1. 判断dataSource是否close
  2. 判断dataSource是否enable
  3. 判断等待获取连接线程数是否已经大于maxWaitThreadCount
  • 创建物理连接后
  1. 设置autoCommit
  2. 设置readOnly
  3. 设置事务隔离
  4. 执行初始化sql:connectionInitSqls
  5. 执行验证sql:validationQuery
  • 获取到连接后
  1. testOnBorrow。执行validationQuery
  2. testWhileIdle。 默认连接最大空余时间:60s。空余时间 = currentTimeMillis - lastActiveTimeMillis。 如果超出了最大空余时间,那么就丢弃这个连接(同时关闭这个连接),重新获取。 为什么要这样做呢?是因为mysql也有这样的限制, 超过最大空闲就不能用了么?那也没有看到初始化的时候配置msql这个属性啊。 同样是使用validationQuery继续测试。

最后

从源码的分析看到,druid设计connections时,connections中的连接是通过创建时间排序的。CreateConnectionThread创建出来的线程是追加到connections的尾部,也就是说connections中第一个连接创建时间是最长的,最后一个连接是最新创建的连接。

同时获取连接时,也是从connections的尾端获取的,最新创建的连接反而会最先被获取。为什么需要这样设计,可以从shrink方法中看到一些原因。在后续的文章中会介绍。

转载于:https://my.oschina.net/everxu/blog/1630166

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值