一 概念
几乎所有的应用程序都不可避免地要与数据库打交道,需要建立数据库连接以便执行数据库操作。 然而, 建立数据库连接是一个开销很大的操作(见《SQL语言艺术》P30):
1. 由于数据库请求通常是跨主机的C-S模式,因此,需要在客户端进程和服务端进程之间完成网络通信必须的握手协议;
2. 首先,客户端与远程服务端的监听程序建立联系; 接着, 监听程序要么创建一个进程或线程来执行数据库核心程序,要么直接或间接把客户请求传递给已存在的服务器进程;
3. 数据库系统还必须为每次Session建立新环境以跟踪;建立新Session前,还要检查密码、登录触发器、初始化存储过程和程序包等。
因此,应用系统通常会创建数据库连接池来管理数据库连接。 从资源角度来看, 数据库连接池就是应用系统的一个资源缓存。
从连接池的需求来看,连接池是一个能够控制数据库连接弹性变化的管理程序,需要满足如下需求:
1. 针对每个数据库, 预先建立一个连接池,其中预置若干个可用连接; 一个数据库对应一个连接池,这就存在一个 DBKEY 到 DB-ConnectionPool的映射;
2. 当少量数据库请求到来时, 可以复用已有连接迅速执行数据库操作;
3. 当大量数据库请求到来时, 可以迅速建立新的连接来满足; 同时当请求处理完成后若干时间后,可以回收连接,保证连接池的连接数在合理范围内。
可以看出, 关于数据库连接池有如下几个基本概念:
1. Connection对象: 描述基本的数据库连接, 例如 ip,port, user, passwd, dbname 等;
2. DataSource 对象: 在 Connection 对象上添加用于连接池管理或事务管理的若干属性,通常使用 JNDI 服务来查询数据源;
3. ConnectionPool 对象: 针对每个DataSource 对象建立的相应连接池对象;在 DataSource 和 ConnectionPool 之间存在一对一的映射。ConnectionPool 必须有一个唯一标识,用于确定获取何种DataSource对象;
4. ConnectionPoolManager对象: 管理所有数据库连接池的连接池管理者,是一个单例对象。
二 Proxool 连接池的重要类及参数
所有与应用直接相关的类基本上都在org.logicalcobwebs.proxool 包里。
1. ProxyConnection: Proxool 提供的 Connection 实现, 采用 Proxy 模式;
2. ProxoolDataSource : Proxool 提供的 DataSource 实现, 必须提及的是, 它有一个不起眼却极其重要的 alias 属性, 而这个属性是 ProxoolDataSource 对象对应连接池的唯一标识。如果多个 ProxoolDataSource 具有同一个 alias ,那么, Proxool 就无法确定该获取哪个 DataSource 对象,就会连接到错误的数据库上; 一个ProxoolDataSource对应一个数据库配置;
3. ConnectionPool: Proxool 提供的对应ProxoolDataSource的连接池对象实现, 数据库连接的获取及管理都是由它委托ProxyConnection来完成的;
4. ConnectionPoolDefinition: ConnectionPool的连接池属性定义及含义说明;
5. ConnectionPoolManager: 连接池映射管理,维护ProxoolDataSource到ConnectionPool的映射关系,其中 key 为 ProxoolDatSource的alias属性;
6. ProxoolFacade: 注册、移除、监听连接池的对象, 采用了Façade模式
7. Prototyper: 主要包含 sweep 和 buildConnection两个方法; 其任务是, 定期扫描指定线程池, 在当前连接数小于所设置的最小连接数或空闲连接数时为其创建新的数据库连接,一个ConnectionPool对应一个Prototyper;
8. PrototyperThread及PrototyperController: 由PrototyperController 启动 PrototyperThread 线程, 这会触发所有连接池的Prototyper 任务。该任务会在移除数据库连接以及 HouseKeeper 任务的末尾触发。
9. HouseKeeper: 主要方法为sweep, 执行数据库连接池的扫描任务, 一个ConnectionPool对应一个HouseKeeper。
10. HouseKeeperThread及HouseKeeperController: 由HouseKeeperController启动HouseKeeperThread线程, 触发所有连接池的HouseKeeper任务。
当注册ConnectionPool到ConnectionPoolManager时,会启动该连接池的任务。在该任务中,会创建此连接池对应的HouseKeeper 和Prototyper, 并注册到 HouseKeeperController中, 这会触发所有已有HouseKeeper的任务, 每个HouseKeeper任务在其将要完成时又会触发Prototyper任务。
重要的连接池参数说明:
1. Alias: 连接池标识, 用于确定从何处获取数据库连接池, 每个ProxoolDataSource 必须具有不同的 alias;
2. prototypeCount: 始终保持的空闲连接数, 用于当数据库请求到来时快速执行操作而无需建立新的数据库连接;
如果 prototypeCount=5, 而当前空闲连接为3,则为另外创建2个连接;
3. MaximumConnectionCount: 可以允许存在的最大连接数;
4. MinimumConnectionCount: 保持打开状态的最小连接数;
5. MaximumConnectionLifetime(ms): 数据库连接在被回收之前可存活的最大时长;
6. MaximumActiveTime: 线程可存活的最大时长。
7. SimultaneousBuildThrottle: 为避免连接创建过载, 所允许的同时创建(处于未完成状态)的最大连接数;
8. HouseKeepingTestSql: 用于测试连接是否可用的SQL语句,必须快而可靠;
9. HouseKeepingSleepTime(ms): 检测连接状态的线程休眠间隔。也就是说,每隔 HouseKeepingSleepTime 时长, 就会进行一次连接状态检测, 将超过连接时长或活动时长的连接进行回收。
10. isTestBeforeUse: 是否在使用连接之前使用HouseKeepingTestSql测试连接可用;
11. isTestAfterUse:是否在使用关闭之后回收到连接池使用HouseKeepingTestSql测试连接可用;