1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > tomcat jdbc数据库连接池详解之PoolCleaner

tomcat jdbc数据库连接池详解之PoolCleaner

时间:2020-01-31 19:57:42

相关推荐

tomcat jdbc数据库连接池详解之PoolCleaner

PoolCleaner是一个定时任务,该任务在创建线程池时自动启动,该任务定期执行哪些工作呢,带着这个问题进入源码:

@Overridepublic void run() {ConnectionPool pool = this.pool.get();if (pool == null) {stopRunning();} else if (!pool.isClosed() &&(System.currentTimeMillis() - lastRun) > sleepTime) {lastRun = System.currentTimeMillis();try {if (pool.getPoolProperties().isRemoveAbandoned())pool.checkAbandoned();if (pool.getPoolProperties().getMinIdle() < pool.idle.size())pool.checkIdle();if (pool.getPoolProperties().isTestWhileIdle())pool.testAllIdle();} catch (Exception x) {log.error("", x);}}}

而checkAbandoned、checkIdle、testAllIdle的执行是受条件约束的,比如checkAbandoned必须在连接池属性removeAbandoned配置为true时才会执行,更多tomcat jdbc连接池配置请参考官网:/tomcat-8.5-doc/jdbc-pool.html

下面将一一介绍checkAbandoned、checkIdle、testAllIdle三个任务到底做了些什么工作,

/**checkAbandoned会清除一些使用时间过长的数据库连接,要注意的是这部分工作针对的就是使用中的数据库连接,及ConnectionPool类BlockingQueue<PooledConnection> busy属性!!**/public void checkAbandoned() {try {if (busy.size()==0) return;Iterator<PooledConnection> locked = busy.iterator();int sto = getPoolProperties().getSuspectTimeout();while (locked.hasNext()) {PooledConnection con = locked.next();boolean setToNull = false;try {//操作之前加锁con.lock();//该连接已被移至idle队列中if (idle.contains(con))continue;long time = con.getTimestamp();long now = System.currentTimeMillis();if (shouldAbandon() && (now - time) > con.getAbandonTimeout()) {//从busy队列中移除该连接busy.remove(con);//废弃该连接abandon(con);setToNull = true;} else if (sto > 0 && (now - time) > (sto*1000)) {//将该连接列为疑似要被废弃状态并发送废弃消息suspect(con);} else {//do nothing} //end if} finally {con.unlock();if (setToNull)con = null;}} //while} catch (ConcurrentModificationException e) {log.debug("checkAbandoned failed." ,e);} catch (Exception e) {log.warn("checkAbandoned failed, it will be retried.",e);}}protected boolean shouldAbandon() {if (poolProperties.getAbandonWhenPercentageFull()==0) return true;float used = busy.size();float max = poolProperties.getMaxActive();float perc = poolProperties.getAbandonWhenPercentageFull();return (used/max*100f)>=perc;}

shouldAbandon方法busy状态的连接是否可以被废弃,被废弃需要满足以下条件:

busy态连接数/最大允许存活量>最大允许的存活比例

//该任务针对的是idle队列的连接,即ConnectionPool的BlockingQueue<PooledConnection> idle属性public void checkIdle(boolean ignoreMinSize) {//ignoreMinSize传入值为falsetry {if (idle.size()==0) return;long now = System.currentTimeMillis();Iterator<PooledConnection> unlocked = idle.iterator();//当前idle队列数目大于连接池设置的minIdle值,需要释放多余的空间连接while ( (ignoreMinSize || (idle.size()>=getPoolProperties().getMinIdle())) && unlocked.hasNext()) {PooledConnection con = unlocked.next();boolean setToNull = false;try {con.lock();//the con been taken out, we can't clean it up//idle跟busy队列中数据可以互相转换,到底怎么转换的后期文章将会介绍if (busy.contains(con))continue;long time = con.getTimestamp();//具体看下面的shouldReleaseIdle方法if (shouldReleaseIdle(now, con, time)) {release(con);idle.remove(con);setToNull = true;} else {//do nothing} //end if} finally {con.unlock();if (setToNull)con = null;}} //while} catch (ConcurrentModificationException e) {log.debug("checkIdle failed." ,e);} catch (Exception e) {log.warn("checkIdle failed, it will be retried.",e);}}protected boolean shouldReleaseIdle(long now, PooledConnection con, long time) {if (con.getConnectionVersion() < getPoolVersion()) return true;//getReleaseTime返回的是连接池的minEvictableIdleTimeMillis配置,这个参数决定了一个连接在被废弃前所允许的最大idle时间else return (con.getReleaseTime()>0) && ((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle());}

//在空闲期检测所有的idle队列中连接public void testAllIdle() {try {if (idle.size()==0) return;Iterator<PooledConnection> unlocked = idle.iterator();while (unlocked.hasNext()) {PooledConnection con = unlocked.next();try {con.lock();//the con been taken out, we can't clean it upif (busy.contains(con))continue;//如果该连接检验失败则可以从idle队列移除,并释放该数据库连接,由于使用数据库连接池的连接是从idle队列中获取的,为了保证连接的有效性需要定期检测这些连接,有些连接可能会被数据库服务端关闭,如果不校验就使用,很可能会使用到无效的连接!if (!con.validate(PooledConnection.VALIDATE_IDLE)) {idle.remove(con);release(con);}} finally {con.unlock();}} //while} catch (ConcurrentModificationException e) {log.debug("testAllIdle failed." ,e);} catch (Exception e) {log.warn("testAllIdle failed, it will be retried.",e);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。