C3P0连接池初始化过程分析之二

Posted 百里马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C3P0连接池初始化过程分析之二相关的知识,希望对你有一定的参考价值。

上一篇我们讲到了C3P0PooledConnectionPool,并且最后说到C3P0PooledConnectionPool中的很多关于连接的操作都委托给了BasicResourcePool来处理,那么下面就隆重请出今天的主角——BasicResourcePool及其帮手——BasicResourcePoolManager。不过写了半天觉得BasicResourcePoolManager的结构和源码太过于复杂,写起博客来压力太大,所以这一篇先来介绍BasicResourcePool中的核心任务。注意,这里只会对这些任务的功能做一个介绍,并介绍会影响任务的各种参数:

核心成员变量

下面这些成员变量先有个了解就好,后续也许会用到

    /*  Key是池中的每个连接,Value是PunchCard类型 */ 
    HashMap  managed = new HashMap();

    /* 可用连接 */
    LinkedList unused = new LinkedList();

    /* 失效但是仍在使用的连接 */
    HashSet  excluded = new HashSet();

    /* 正在进行闲置检测的连接 */
    Set idleCheckResources = new HashSet();

    /* 正在使用却因某些原因失效的连接 */
    HashSet  excluded = new HashSet();

    /* 先前的连接 */
    Map formerResources = new WeakHashMap();

    /* 需要达到的连接池大小,会根据它和当前的连接池大小以及等待获取的队列大小计算出是扩容还是收缩 */
    int target_pool_size;

    /* 正在进行中的获取连接数 */
    int pending_acquires;
    /* 正在进行中的移除连接数 */    
    int pending_removes;

    /* 获取连接的Set */
    HashSet acquireWaiters = new HashSet();

ScatteredAcquireTask

从数据库获取连接任务,该任务替代了之前的AcquireTask

相关连接池参数:

  • acquireRetryAttempts对应num_acq_attempts,代表获取连接失败后重试的次数
  • acquireRetryDelay对应acq_attempt_delay,代表连接失败后,开启新任务的延迟

光有上述两个参数你可能不太理解C3P0对于重试的具体做法:当获取连接任务失败时,若重试次数大于0,那么会在 延迟一段时间之后 开启重试线程再次去获取连接,并且该新线程的重试次数会递减1。注意:上述失败均指的是抛出异常

那么何时需要去数据库获取新连接呢?肯定是连接不够用了嘛。比如此时用户请求上来,独占了一条线程,跑到需要执行SQL的地方,发现连接池中的连接不够用了,那么它会触发连接池扩容(异步),并且自身会等待到池中获取到第一个连接,这里又会涉及到几个连接池的参数:

  • checkoutTimeout对应checkoutTimeout,代表等待获取连接超时时间,也就是 用户请求最长等待可用连接的时间
  • acquireIncrement对应inc,代表每次需要扩容时的扩容量

RemoveTask

这个任务和上一个任务相反,用来移除和销毁连接


CullTask

用来销毁过期的连接,该任务为定时任务

任务执行周期:

这里分两种情况:

  1. 一种可以显式指定运行周期,也就是通过配置下面的参数: propertyCycle对应expiration_enforcement_delay
  2. 如果不显示指定运行周期,那么会通过以下参数计算出一个周期:

    • maxConnectionAge对应max_resource_age,代表连接时长
    • maxIdleTime对应max_idle_time,代表最大过期时长
    • maxIdleTimeExcessConnections对应excess_max_idle_time,代表
    • unreturnedConnectionTimeout对应destroy_unreturned_resc_time,代表最大允许连接被checkout的时长

从这4个参数中取出最小的一个,当然小于等于0时不作考虑。然后会以最小值来除以4作为该任务的运行周期

初次执行任务延迟:

也分两种情况:

  1. 显式指定时,即为propertyCycle
  2. 不显式指定,那么即从这4个参数中取出最小的一个,当然小于等于0时不作考虑。这个延迟不会除以4

相关连接池参数:

  • unreturnedConnectionTimeout对应destroy_unreturned_resc_time,代表最大允许连接被checkout的时长,超过这个时间后连接会被销毁。如果这个时间小于等于0,那么则没有限制。
  • propertyCycle对应expiration_enforcement_delay,代表显示指定的任务执行周期

CheckIdleResourcesTask

用来对闲置的连接进行有效性检测,该任务也为定时任务

任务执行周期:

通过参数idleConnectionTestPeriod对应check_idle_resources_delay手动指定,小于等于0时此任务不执行,也就是不进行闲置连接的有效性检测

初次执行任务延迟:

与任务的执行周期一致

相关连接池参数:

  • idleConnectionTestPeriod对应check_idle_resources_delay,代表任务执行的周期,小于等于0时此任务不执行,也就是不进行闲置连接的有效性检测

如何定义闲置连接:

不要紧张,这只是个文字游戏,此处的闲置连接也就是所有未使用的连接而已

以上是关于C3P0连接池初始化过程分析之二的主要内容,如果未能解决你的问题,请参考以下文章

C3P0整体类结构简单分析2

数据库连接池——C3P0

如何修复 c3p0 连接池初始化异常?

数据库连接池c3p0和Druid使用教程

JavaEE基础(06):Servlet整合C3P0数据库连接池

c3p0数据库连接池 原创: Java之行 Java之行 5月8日 连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程