再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!( 三 )

  • pollLast 方法:从池中拿连接,并最多等待 maxWait 的时间 , 需要设置了maxWait;

  • 再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    pollLast 方法的核心是:死循环内部 , 通过 Condition 对象 notEmpty 的 awaitNanos 方法执行等待,若池子中有连接,将最后一个连接取出,并将最后一个数组元素置为空 。
    takeLast 方法:从池中拿连接 , 并一直等待直到拿到连接 。
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    和 pollLast 方法不同 , 首先方法体内部并没有死循环,通过 Condition 对象 notEmpty 的 await 方法等待,直到池子中有连接,将最后一个连接取出,并将最后一个数组元素置为空 。
    3.4 归还连接DruidDataSource 连接池中 , 每一个物理连接都会被包装成DruidConnectionHolder,在提供给应用线程前,还会将 DruidConnectionHolder 包装成 DruidPooledConnection 。
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    原生的 JDBC 操作,每次执行完业务操作之后,会执行关闭连接,对于连接池来讲,就是归还连接,也就是将连接放回连接池 。
    下图展示了 DruidPooledConnection 的 close 方法 :
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    在关闭方法中,我们重点关注 recycle 回收连接方法 。
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    我们可以简单的理解:将连接放到 connections 数组的 poolingCount 位置 , 并将其自增,然后通过 Condition 对象 notEmpty 唤醒等待获取连接的一个应用程序 。
    3.5 销毁连接DruidDataSource 连接的销毁 DestroyConnectionThread 线程完成 :
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    从定时任务(死循环)每隔 timeBetweenEvictionRunsMillis 执行一次,我们重点关注destroyTask的run方法 。
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    destroyTask的run方法 会调用DruidDataSource#shrink方法来根据设定的条件来判断出需要销毁和保活的连接 。
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    核心流程:
    1)遍历连接池数组 connections:
    内部分别判断这些连接是需要销毁还是需要保活,并分别加入到对应的容器数组里 。
    2)销毁场景:
    • 空闲时间idleMillis  >= 允许的最小空闲时间 minEvictableIdleTimeMillis
    • 空闲时间idleMillis  >= 允许的最大空闲时间 maxEvictableIdleTimeMillis
    3)保活场景:
    • 发生了致命错误(onFatalError == true)且致命错误发生时间(lastFatalErrorTimeMillis)在连接建立时间之后
    • 如果开启了保活机制,且连接空闲时间大于等于了保活间隔时间
    4)销毁连接:
    遍历数组 evictConnections 所有的连接,并逐一销毁。
    5)保活连接:
    遍历数组 keepAliveConnections 所有的连接 , 对连接进行验证,验证失败 , 则关闭连接,否则加锁,重新加入到连接池中 。
    4 保证连接有效本节,我们讲解如何合理的配置参数保证数据库连接有效 。
    很多同学都会遇到一个问题:“长时间不进行数据库读写操作之后,第一次请求数据库,数据库会报错,但第二次就正常了 。"
    那是因为数据库为了节省资源,会关闭掉长期没有读写的连接 。
    笔者第一次使用 Druid 时就遇到过这样的问题,有兴趣的同学可以看看笔者这篇文章:
    https://www.javayong.cn/codelife/runningforcode.html
    下图展示了 Druid 数据源配置样例:
    再有人问你数据库连接池 Druid 的原理,这篇文章甩给他!

    文章插图
    图片
    我们简单梳理下 Druid 的保证连接有效有哪些策略:
    1、销毁连接线程定时检测所有的连接,关闭空闲时间过大的连接 ,假如配置了保活参数,那么会继续维护待保活的连接;


    推荐阅读