当前位置: 首页 > wzjs >正文

银川做淘宝网站的爱链

银川做淘宝网站的,爱链,哪个网站可以学做咸菜,微信小程序开发哪家好目录 为什么需要JDBC连接池 Tomcat JDBC Pool 相关参数 1. 基本配置 2. 连接池大小控制 3. 连接验证与测试 4. 空闲连接回收 5. 连接泄漏与超时 Tomcat JDBC Pool 源码分析(tomcat 8.5.3) DataSourceFactory DataSource ConnectionPool Pool…

目录

为什么需要JDBC连接池

Tomcat JDBC Pool 相关参数

1. 基本配置

2. 连接池大小控制

3. 连接验证与测试

4. 空闲连接回收

5. 连接泄漏与超时

Tomcat JDBC Pool 源码分析(tomcat 8.5.3)

DataSourceFactory

DataSource

ConnectionPool

PoolCleaner


对于JAVA开发者来说,JDBC肯定都比较熟悉,它其实是Java提供了一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程即可,不同的数据库厂商需要针对这套接口提供不同的实现。

为什么需要JDBC连接池

使用传统的jdbc做开发时,一方面频,繁的进行数据库连接操作将占用很多的系统资源,另一方面,每次拿到connection使用完都要主动去断开,那如果程序出现异常导致链接没有关闭,就会发生内存会泄露,因此可以发现使用jdbc开发时在连接管理上是存在风险的。另外,用传统的连接方法无法控制程序中创建的连接数量,如果连接过多也会导致内存泄漏。

那JDBC连接池的作用,就是可以避免频繁创建连接,帮我们做连接的生命周期管理,以及在请求较大时控制应用内连接的数量防止出现崩溃。

目前java生态里主流的JDBC连接池有HikariCP,Druid等,还有本文写的Tomcat JDBC Pool。

Tomcat JDBC Pool 相关参数

下面列举了一些基本参数和连接管理方面检测机制相关的参数

1. 基本配置

  • driverClassName
    数据库驱动类名(如 com.mysql.jdbc.Driver)。
  • url
    数据库连接 URL(如 jdbc:mysql://localhost:3306/mydb)。
  • username
    数据库用户名。
  • password
    数据库密码。

2. 连接池大小控制

  • initialSize
    连接池初始化时创建的连接数(默认 0)。
  • maxActive
    最大活跃连接数(默认 100)。
  • maxIdle
    最大空闲连接数(默认与 maxActive 相同)。
  • minIdle
    最小空闲连接数(默认 0)。
  • maxWait
    获取连接的最大等待时间(毫秒,默认 30000,超时抛异常)。

3. 连接验证与测试

  • testOnBorrow
    从池中获取连接时是否验证有效性(默认 false)。
  • testOnReturn
    归还连接时是否验证有效性(默认 false)。
  • testWhileIdle
    空闲时是否定期验证连接(默认 false)。
  • validationQuery
    用于验证连接的 SQL 查询(如 SELECT 1)。
  • validationQueryTimeout
    验证查询的超时时间(秒,默认 -1 表示无限制)。

4. 空闲连接回收

  • timeBetweenEvictionRunsMillis
    空闲连接检查线程的运行间隔(毫秒,默认 5000)。
  • minEvictableIdleTimeMillis
    连接被回收前的最小空闲时间(默认 60000)。
  • numTestsPerEvictionRun
    每次检查回收的空闲连接数(默认使用所有空闲连接)。

5. 连接泄漏与超时

  • removeAbandoned
    是否自动回收泄露的连接(默认 false)。
  • removeAbandonedTimeout
    连接被标记为泄露的时间阈值(秒,默认 60)。
  • logAbandoned
    是否记录泄露连接的堆栈信息(默认 false)。

     

Tomcat JDBC Pool 源码分析(tomcat 8.5.3)

下面简单分析下tomcat连接池是如何创建,又是如何实现连接检测的。

DataSourceFactory

DataSourceFactory是Tomcat JDBC Pool 中用来创建DataSource的工厂类,这个类在org.apache.tomcat.jdbc.pool包下。

下面是类中与连接池创建相关的部分代码片段:

public DataSource createDataSource(Properties properties) throws Exception {return createDataSource(properties,null,false);
}public DataSource createDataSource(Properties properties,Context context, boolean XA) throws Exception {PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties);if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) {performJNDILookup(context, poolProperties);}org.apache.tomcat.jdbc.pool.DataSource dataSource = XA? new org.apache.tomcat.jdbc.pool.XADataSource(poolProperties) : new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);//创建连接池dataSource.createPool();return dataSource;
}

可以看到 DataSourceFactory.createDataSource 方法返回一个DataSource实例,DataSource初始化后调用了 createPool 方法来初始化连接池相关的组件。

DataSource

DataSource是内置了数据源连接池 ConnectionPool 的对象,基于JDBC标准对外提供了一些方法。

Tomcat JDBC Pool 中支持两种DataSource类型,一种是普通DataSource,另一种是XADataSourced。

ConnectionPool

ConnectionPool 就是连接池最核心的资源对象,但是他不会直接对外暴露,而是被包装在上面说的DataSource中,开发过程中通常先获取到的是DataSource对象实例。

了解了DataSource 和 ConnectionPool 后,继续来看DataSourceFactory.createDataSource 方法中的createPool方法逻辑,这个方法在DataSource或XADataSourced共同的父类DataSourceProxy,打开DataSourceProxy类可以进一步看具体的方法内容:

public ConnectionPool createPool() throws SQLException {if (pool != null) {return pool;} else {return pCreatePool();}
}/*** Sets up the connection pool, by creating a pooling driver.*/
private synchronized ConnectionPool pCreatePool() throws SQLException {if (pool != null) {return pool;} else {pool = new ConnectionPool(poolProperties);return pool;}
}
public ConnectionPool(PoolConfiguration prop) throws SQLException {init(prop);
}

 createPool  方法最终后调用到 init 方法:

protected void init(PoolConfiguration properties) throws SQLException {poolProperties = properties;//make sure the pool is properly configuredcheckPoolConfiguration(properties);//make space for 10 extra in case we flow over a bitbusy = new LinkedBlockingQueue<>();//busy = new FairBlockingQueue<PooledConnection>();//make space for 10 extra in case we flow over a bitif (properties.isFairQueue()) {idle = new FairBlockingQueue<>();//idle = new MultiLockFairBlockingQueue<PooledConnection>();//idle = new LinkedTransferQueue<PooledConnection>();//idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);} else {idle = new LinkedBlockingQueue<>();}initializePoolCleaner(properties);//create JMX MBeanif (this.getPoolProperties().isJmxEnabled()) createMBean();//Parse and create an initial set of interceptors. Letting them know the pool has started.//These interceptors will not get any connection.PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();for (int i=0; i<proxies.length; i++) {try {if (log.isDebugEnabled()) {log.debug("Creating interceptor instance of class:"+proxies[i].getInterceptorClass());}JdbcInterceptor interceptor = proxies[i].getInterceptorClass().getConstructor().newInstance();interceptor.setProperties(proxies[i].getProperties());interceptor.poolStarted(this);}catch (Exception x) {log.error("Unable to inform interceptor of pool start.",x);if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));close(true);SQLException ex = new SQLException();ex.initCause(x);throw ex;}}//initialize the pool with its initial set of membersPooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];try {for (int i = 0; i < initialPool.length; i++) {initialPool[i] = this.borrowConnection(0, null, null); //don't wait, should be no contention} //for} catch (SQLException x) {log.error("Unable to create initial connections of pool.", x);if (!poolProperties.isIgnoreExceptionOnPreLoad()) {if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));close(true);throw x;}} finally {//return the members as idle to the poolfor (int i = 0; i < initialPool.length; i++) {if (initialPool[i] != null) {try {this.returnConnection(initialPool[i]);}catch(Exception x){/*NOOP*/}} //end if} //for} //catchclosed = false;
}

这个方法中执行了 initializePoolCleaner 这个方法

 public void initializePoolCleaner(PoolConfiguration properties) {//if the evictor thread is supposed to run, start it nowif (properties.isPoolSweeperEnabled()) {poolCleaner = new PoolCleaner(this, properties.getTimeBetweenEvictionRunsMillis());poolCleaner.start();} //end if}

initializePoolCleaner 方法的逻辑是初始化一个PoolCleaner,然后启动它。

注意初始化这个构造器,传入了一个关键参数:

betweenEvictionRunsMillis

这个参数用来指定对于空闲链接检测的任务多久执行一次,默认值是5000ms,默认值实在 org.apache.tomcat.jdbc.pool.PoolProperties 类中定义的固定值,如果外部设置了会覆盖。

PoolCleaner

PoolCleaner 是 ConnectionPool 中的一个内部静态类。这个类继承TimerTask ,实例化后其实是一个线程任务,Tomcat JDBC Pool 就是通过启动这个定时任务来实现连接池中的各种检测功能。

run方法中就是检测任务的具体逻辑,包括:

1.对最小连接数的维护,数量少于最小连接数则新建补充,数量多了则销毁多余的。

2.对空闲链接的检测,如果 testWhileIdle 参数设置为true,那在任务每次执行时会获取一定数量的链接,判断是否可用,如果不可用就销毁。

 protected static class PoolCleaner extends TimerTask {protected WeakReference<ConnectionPool> pool;protected long sleepTime;PoolCleaner(ConnectionPool pool, long sleepTime) {this.pool = new WeakReference<>(pool);this.sleepTime = sleepTime;if (sleepTime <= 0) {log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds");this.sleepTime = 1000 * 30;} else if (sleepTime < 1000) {log.warn("Database connection pool evicter thread interval is set to lower than 1 second.");}}@Overridepublic void run() {ConnectionPool pool = this.pool.get();if (pool == null) {stopRunning();} else if (!pool.isClosed()) {try {if (pool.getPoolProperties().isRemoveAbandoned()|| pool.getPoolProperties().getSuspectTimeout() > 0)pool.checkAbandoned();if (pool.getPoolProperties().getMinIdle() < pool.idle.size())pool.checkIdle();if (pool.getPoolProperties().isTestWhileIdle())pool.testAllIdle();} catch (Exception x) {log.error("", x);}}}public void start() {registerCleaner(this);}public void stopRunning() {unregisterCleaner(this);}}

http://www.dtcms.com/wzjs/107870.html

相关文章:

  • 网站指向错误迈步者seo
  • 做搜狗pc网站优化点b站推广是什么意思
  • 西宁企业网站建设开发关键词优化策略有哪些
  • 做网站公司会场主持台词广东百度seo关键词排名
  • 商洛网站建设百度推广的广告靠谱吗
  • 报纸门户网站建设方案电商seo什么意思
  • 现在都用什么软件做网站灰色关键词排名优化
  • 湖南新备案的网站怎么开发一款app软件
  • 网站建设 南宁学推广网络营销去哪里
  • 宁国做网站的搜狗网站排名软件
  • 个人微信做网站客服怎么提高关键词搜索排名
  • 建设银行大学华东学院网站媒体资源网官网
  • 图片制作在线网页seo实战密码电子版
  • 网站建设招聘兼职西安楼市最新房价
  • 公司企业网站源码网站排名优化推广
  • wordpress 多说头像搜索引擎优化的方式
  • 武汉做网站推广哪家好济南全网推广
  • 给博彩做网站软件开发外包平台
  • 小程序可以用手机网站吗一键生成app制作器
  • 代做网站 作业上海seo
  • wordpress分类标题nothing found开封网站快速排名优化
  • 做缓网站网络营销的优势
  • 网站评论区怎么做南宁seo优化公司
  • 用php做网站后台推广产品的文案
  • 温州建网站电商代运营十大公司排名
  • 合肥网站设计哪家公司好优化公司网站排名
  • 网站文章不收录怎么做网址大全下载
  • 深圳网站建设公司哪家广告视频
  • html 动漫网站网络营销效果评估
  • 做网站销售好吗seo入门教程