登录
2022-05-14 00:33:56

连接池技术 免费编辑 添加义项名

B 添来自加义项
?
义项指多义词的不同宗而部增零干状概念,如李娜的义项:网球360百科运动员、歌手等;非诚勿扰灯唱地位义项:冯小刚执导电影、江苏卫视交友节目等。 查看详细规范>>
属类别 :
数理逻辑
数理逻辑
编辑分类

连接池技术的核心思想是:连接复用,通过建立一个数据库连接池以及一套连接使用、分配、管理策略,使得该连接池中的连接可以得到高效、安全的复用,避免了数据库连接频繁建立、关闭的开销。另外,由于对JDBC中的原始连接进行了封装,从而方便了数据库应用对于连接的使用(特别是对于事务处理),提高了获取数据库连接效率,也正是因为这个封装层的存在,隔离了应用的本身的处理逻辑和具体数据库访问逻辑,使应用本身的复用成为可能。连接池主要由三部分组成:连接池的建立、连接池中连接的使用管理、连接池的关闭。

折叠 编辑本段 连接池的建立

应用程序中建立的连接池其实是一个静态的。所谓静态连封编蛋富坚接池是指连接池中的连接在系统初始化时就已分配好,且不能随意关闭连接。Java中提供了很多容器类可以方便的构建连接池,如:破耐尽苦停南倒振迅职Vector、Stack、Servlet、Bean等,通过读取连接属性文件Connections.properties与数据库实例建立连接。在系统初始化时,根据相应的配置创建连接并放置在连接池中,以便需要使用时能从连接池中获取,这样就可以避县夫然龙品确伤稳免连接随意的建立、关闭造成升限工丝的开销。

折叠 连接池的管理

连接池管理策略是连接池机制的核心。当连接池建立后,如何对连接池中的连接进行管理,解决好连接池需标句代决周促需挥连接的分配和释放,对系统的性能有很大的影响。连接的合理分配、释放可提高连接的复用,降低了系统建立新连接的开销,同时也加速了用户的访问速度。下面介绍连接池中连接的分配、释放策略。

连接池的分配、释放策略对于有效复用连接非常重要,我们采用的方法是一个很有名的设计模式:Reference Counting(引用记数)。该模式在复用资源方面应用的非常广泛,把该方法运用到对于连接的分配释放上,为每一个数据库连接,保留一个引用记数,用来记录该连接的使用者的个数。具体的实现方法是:

当客户请求数据库连接时,首先查看连接池中是否有空闲连接(指当前没有分配出去的连接)。如果存在空闲连接,则把连接分真历宽听守移双配给客户并作相应处理(味祖末即标记该连接为正在使用,引用计数加1)。如果没有空闲连接,则查看当前所开的连接数是不是已经达到maxConn排程虽道(最大连接数),如果没绍判查题审表车们协八致达到就重新创建一都判随家抓然聚京切个连接给请求的客户;如果达到就按设定的maxWaitTime(最大等待时间)进行等待,如果等待maxWaitTime后仍没有空闲连接,就抛出无空闲连接的异常给用户。

当客户释放数据库连接时,先判断该连接的引用次数是否手倒报超过了规定值,如果超过就删除该连接,并判断当前连接池内总的连接数是否小于minConn(最小连接数),若小于控治静就将连接池充满;如果没超过就将该连接标记为开放状包础请难题存态,可供再次复用。可以看出正是这套策略保证了数据库连接的有效复用,避免频繁地建立、到对错与演释放连接所带来的系统资源开销。

折叠 连接池的关闭

当应用程序退出时,应关闭连接停记伟总,此时应把在连接池建立时向数据库申请的连接对象统一归还给数据库(即关闭所有数据库连接),这与连接池的建立正好是一个相反过程。

折叠 连接池的配置

数据库连接池中到底要放置多少个连接,才能使系统的性能更佳,用minConn和maxConn来限制。minConn是当应用启动的时候连接池所创建的连接数,如果过大启动将变慢,但是启动后响应划因星跳列深苏预灯更快;如果过小启动高父加快,但是最初使用的用户将因为连接池中没有足够的连接不可避免的延缓了执行速度。因此应该在开发的过程中设定较小minConn,而在实际应用的中设定较大minConn。maxConn是连接池中的最大连接数,可以通过反复试验来确定此饱和点。为此在连接池类Connectio协及计nPool中加入两个方法getActiveSiz问限建放较眼张细e()和getOpenSize(),ActiveSize 表示某一时间有多少连接正被使用,Open增周种主然宣尼在音数Size表示连接池中有多少连接被打开,反映了连接池使用的峰值。将这两个值在日志信息中反应出来, minConn的值应该小于平均ActiveSize,而maxConn的值应该在李著界液车白activeSize和OpenSize之间。

折叠 编辑本段 连接池的关键技术

折叠 事务处理

前面讨论的是关于使用数据库连接进行普通的数据库访问。对于事务处理,情况就变得比较复杂。因为事务本身要求原则性的保证跑士坏止,此时就要求对于数据库的操作符合"All-or-Nothing"原则,即要么全部完成,要么什么都不元厚千万父做。如果简单的采用上述的连接复用的策略,就会发生问题,因为没有办法轻简含现认价新土所控制属于同一个事务的多个数据库操作方法的动作,可能这些数据库操作是在多个连接上进行的,并且这些连接可能被其他非事务方法复用。Connection本身具有提供了对于事务的支持,可以通过设置Connection的AutoCommit属性为false,显式的调用 精友情commit或rollback方法来实现。但是要安全、高效的进行连接复用,就必须提供相应的事务支持机制。方法是:采用显式的事务支撑方法,每一个事务独占一个连接。这种方法可以大大降低对于事务处理的复杂性,并且又不会妨碍连接的复用。

连接管理服务提供了显式的事务开始、结束(commit或rollback)声明,以及一个事务注册表,用于登记事务发起者和事务使用的连接的对应关系,通过该表,使用事务的部分和连接管理部分就隔离开,因为该表是在运行时根据实际的调用情况动态生成的。事务使用的连接在该事务运行取铁课玉上矿就呀根中不能被复用。在实现中,用户二自单绝标识是通过使用者所在的线程来标识的。后面的所有对乐突身于数据库的访问都是通过查找该注册表,使用已经分配的连接来完成的。当事务结束时,从注册表中删除相应表项。

折叠 并发

为了使连接管理只需快危宁度官木施祖甚服务有更大的通用性,消问用我们必须要考虑到多线程环境经与皮副音具直想,即并发问题。在一个多线程的环境下,必须要保证连接管理自身数据的一致性和连接内部数据的一致性,在这方面Java提供很好的支持(synchronized键字),这样就很容易使连接管理成为线程安全的。

折叠 多数据库服务器

在实际应用中,应用程序常常需要自穿何轻差了仅演环力访问多个不同的数据库。克给器讲即如何通过同一个连接池访赶老求问不同的数据库,是应用程序需要解决的一个核心问题。下面介绍一种音速都往纪音补解决的途径:

首先,定义一个数据库连接池参数的类,定义了数据库的JDBC驱动程序类名,连接的URL以及用户名口令等等一些信息,该类是用于初始化连接池的参数:

public class ConnectionParam implements Seriali名想现关察棉差说zable{//各初始化参数的定义}

其次是连接池的工厂类块劳更础就场绝欢教Connectio附扬子女nFactory,通得无答过该类将一个连接池对象与一个名问报缩范的称对应起来,使用者通过该名称就可以获取指定的连接池对象,实现的主要代码如标度下:

public class ConnectionFactory{static Hashtable connectionPools = //用来保存数据源名和连接池对象的关系public static DataSource lookup(String dataS清坐销叫矛如写答艺ourceName) throws

NameNotFoundException{//查找名字为dataSourceName的数据源}public static DataSource bind(Stringname, ConnectionParam param)

throws Exception=/将名字name与使用param初始化的连接池对象绑定

}

public static void unbind(String name) throws NameNotFound

Exception{

//将与名字name绑定的连接池对象删除

}

折叠 编辑本段 连接池应用的实现

一个完整的连接池应用包括三个部分:DBConnectionPool类,负责从连接池获取(或创建)连接、将连接返回给连接池、系统关闭时关闭所有连接释放所有资源;DBConnectionManager类,负责装载和注册JDBC驱动、根据属性文件中定义的属性创建DBConnectionPool、跟踪应用程序对连接池的引用等;应用程序对连接池的使用。

本文实现的数据库连接池包括一个管理类DBConnectionManager,负责提供与多个连接池对象(DBConnectionPool类)之间的接口。每一个连接池对象管理一组封装过的JDBC连接对象Conn,封装过的JDBC连接对象Conn可以被任意数量的Model层的组件共享。

类Conn 的设计很简单,如下所示:

Class Conn {

Private java. sgl .Connection con; //数据库连接对象

Public Boolean inUse ; //是否被使用

Public long lastAccess; //最近一次释放该连接的时间

Public int useCount; // 被使用次数

}

下面是实现连接池的主要代码:

// 初始化数据库连接池

public static synchronized void FastInitPool()

throws Exception {

try { Class.forName(driver);

for (int i=0; i<size; i++) {

Connection con = createConnection();

if (con!=null) addConnection(con);

} } }

// 向连接池对象中添加数据库连接

private static void addConnection(Connection con) {

if (pool==null||pool1==null) {

pool=new Vector(size);

pool1=new Vector(size); }

pool.addElement(con);

pool1.addElement("false"); }

// 获取数据库连接

public static synchronized Connection getConn()

throws Exception {

Connection conn = null;

try { if (driver = null)

FastInitPool();

// 获得一个可用的(空闲的)连接

for (int i = 0; i < pool.size(); i++) {

conn = (Connection)pool.elementAt(i);

if (pool1.elementAt(i)=="false") {

pool1.set(i,"true");

//System.out.println("从连接池中获取第"+(i+1)+"个空闲连接");

return conn;

}

}

//如果没有可用连接,且已有连接数小于最大连接数限制,则创建并增加一个新连接到连接池

conn = createConnection();

pool.addElement(conn);

pool1.addElement("true");

// System.out.println(" 所有连接都在使用,在连接池中再创建一个新连接");

}

catch (Exception e) {

System.err.println(e.getMessage());

throw new Exception(e.getMessage());

}

return conn; //返回一个有效的新连接

}

public Connection getConnection(String strDriver, String strUrl, String strUserName, String strPassWord)

throws SQLException{

try{ Class.forName(strDriver);

conn = DriverManager.getConnection(strUrl, strUserName, strPassWord); }

return conn; }

阅读全文

热点资讯

我的关注