数据库连接池c3p0和dbcp和tomcat-dbcp

来源:互联网 发布:清朗网络 青年力量海报 编辑:程序博客网 时间:2024/05/17 03:53

jdbc(Java DataBase Connection):

是应用程序与数据库沟通的桥梁, 即Java语言通过JDBC技术访问数据库。

一般来说,Java应用程序访问数据库的过程是:

  ①装载数据库驱动程序;

  ②通过JDBC建立数据库连接;

  ③访问数据库,执行SQL语句;

  ④断开数据库连接。


jdbc是一种数据库访问技术,具有简单易用的优点。但在WEB应用程序开发中,存在很多问题
  首先、每一次WEB请求都要建立一次数据库连接,建立连接是个费时的活动,而且过程中系统还要分配内存资源。在高并发情况下,这种频繁的对数据库连接操作势必会降低响应速度,严重的可能导致服务器崩溃;
  其次,对于每次的数据库连接,使用完都得断开,如若连接未能关闭,将会导致数据库系统内存泄漏。最终将不得不重启数据库。
  再者,这种连接方式不能控制被创建的连接数,会将系统资源毫无保留的分配出去,连接数过多,也会导致内存泄漏,导致服务器崩溃。  


  由上面的分析可以看出,问题就出在对数据库资源连接的低效管理。由此,我们在此基础上对JDBC进行优化,提出了数据库连接池(connection pool)
  资源池(resoure pool)主要作用有俩个:控制数量、资源重利用。


连接池的分配与释放:
  已经创建的连接都放入List中去统一管理。每当用户请求一个连接时,系统检查这个List中有没有可以分配的连接。如果有就把那个最合适的连接分配给他;如果没有就抛出一个异常给用户,List中连接是否可以被分配由一个线程来专门管理。
连接池的配置与维护:
  采取设置最小连接数(minConnection)和最大连接数(maxConnection)等参数来控制连接池中的连接,来使系统的性能最佳。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过软件需求上得到。
  如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。  


使用数据库连接池的优势和其工作原理:

  1、连接池的优势:
连接池的主要优点有以下三个方面。
  一、减少连接创建时间。连接池中的连接是已准备好的、可重复使用的,获取后可以直接访问数据库,因此减少了连接创建的次数和时间。

  二、简化的编程模式。当使用连接池时,每一个单独的线程能够像创建一个自己的JDBC连接一样操作,允许用户直接使用JDBC编程技术。

  三、控制资源的使用。如果不使用连接池,每次访问数据库都需要创建一个连接,这样系统的稳定性受系统连接需求影响很大,很容易产生资源浪费和高负载异常。连接池能够使性能最大化,将资源利用控制在一定的水平之下。连接池能控制池中的连接数量,增强了系统在大量用户应用时的稳定性。

  2、连接池的工作原理
  连接池的工作原理主要由三部分组成,分别为连接池的建立、连接池中连接的使用管理、连接池的关闭。
  一、连接池的建立。一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。
  二、连接池的管理。连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:
  >>当客户请求数据库连接时,首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户。
  >>当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。
  >>连接池的关闭。当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。
  


几种常用的数据库连接池

一、DBCP (Database Connection Pool)
  所需jar包:commons-dbcp.jar、commons-pool.jar、commons-collections-3.1.jar
  配置
  

  <!-- 配置dbcp数据源 -->      <bean id="dataSource2" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">        <property name="driverClassName" value="${jdbc.driverClassName}"/>        <property name="url" value="${jdbc.url}"/>        <property name="username" value="${jdbc.username}"/>        <property name="password" value="${jdbc.password}"/>        <!-- 池启动时创建的连接数量 -->        <property name="initialSize" value="5"/>        <!-- 同一时间可以从池分配的最多连接数量。设置为0时表示无限制。 -->        <property name="maxActive" value="30"/>        <!-- 池里不会被释放的最多空闲连接数量。设置为0时表示无限制。 -->        <property name="maxIdle" value="20"/>        <!-- 在不新建连接的条件下,池中保持空闲的最少连接数。 -->        <property name="minIdle" value="3"/>        <!-- 设置自动回收超时连接 -->          <property name="removeAbandoned" value="true" />        <!-- 自动回收超时时间(以秒数为单位) -->          <property name="removeAbandonedTimeout" value="200"/>        <!-- 设置在自动回收超时连接的时候打印连接的超时错误  -->         <property name="logAbandoned" value="true"/>        <!-- 等待超时以毫秒为单位,在抛出异常之前,池等待连接被回收的最长时间(当没有可用连接时)。设置为-1表示无限等待。  -->          <property name="maxWait" value="100"/>        </bean>

二、C3P0
  所需jar包:c3p0-0.9.2.1.jar、mchange-commons-java-0.2.3.4.jar
  配置
  

<!-- 配置c3p0数据源 -->    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">        <property name="jdbcUrl" value="${jdbc.url}" />        <property name="driverClass" value="${jdbc.driverClassName}" />        <property name="user" value="${jdbc.username}" />        <property name="password" value="${jdbc.password}" />        <!--连接池中保留的最大连接数。Default: 15 -->        <property name="maxPoolSize" value="100" />        <!--连接池中保留的最小连接数。-->        <property name="minPoolSize" value="1" />        <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->        <property name="initialPoolSize" value="10" />        <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->        <property name="maxIdleTime" value="30" />        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->        <property name="acquireIncrement" value="5" />        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements          属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。          如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0-->        <property name="maxStatements" value="0" />        <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->        <property name="idleConnectionTestPeriod" value="60" />        <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->        <property name="acquireRetryAttempts" value="30" />        <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效          保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试          获取连接失败后该数据源将申明已断开并永久关闭。Default: false-->        <property name="breakAfterAcquireFailure" value="true" />        <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的          时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable          等方法来提升连接测试的性能。Default: false -->        <property name="testConnectionOnCheckout"  value="false" />            </bean>

三、tomcat 自带的tomcat jdbc pool
  Tomcat默认使用的是DBCP数据库连接池,其实从本质上讲,Tomcat是利用Apache Commons DBCP来实现的,只不过把特定的功能集成到了tomcat-dbcp.jar包中。
  Tomcat 在 7.0 以前的版本都是使用 commons-dbcp 做为连接池的实现,但是 dbcp 饱受诟病,原因有:
  1、dbcp 是单线程的,为了保证线程安全会锁整个连接池
  2、dbcp 性能不佳
  3、dbcp 太复杂,超过 60 个类
  4、dbcp 使用静态接口,在 JDK 1.6 编译有问题
  5、dbcp 发展滞后

为此,Tomcat 从 7.0 开始引入一个新的模块:Tomcat jdbc pool
  1、tomcat jdbc pool 近乎兼容 dbcp ,性能更高
  2、异步方式获取连接
  3、tomcat jdbc pool 是 tomcat 的一个模块,基于 tomcat JULI,使用 Tomcat 的日志框架
  4、使用 javax.sql.PooledConnection 接口获取连接
  5、支持高并发应用环境
  6、超简单,核心文件只有8个,比 c3p0 还
  7、更好的空闲连接处理机制
  8、支持 JMX、支持 XA Connection
  9、tomcat jdbc pool 可在 Tomcat 中直接使用,也可以在独立的应用中使用。
  
配置方法:
方法一、在Tomcat\conf目录下的context.xml文件中Context标签结尾前配置如下内容:

<!--配置oracle数据库的连接池-->    <Resource name="jdbc/oracleds"        author="Container"        type="javax.sql.DataSource"        maxActive="100"        maxIdle="30"        maxWait="10000"        username="scott"        password="tiger"        driverClassName="oracle.jdbc.dirver.OracleDriver"        url="jdbc:oracle:thin:@127.0.0.1:1521:ora9" />    <!--配置mysql数据库的连接池,         需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下                maxIdle 连接池中最多可空闲maxIdle个连接         minIdle 连接池中最少空闲maxIdle个连接         initialSize 初始化连接数目         maxWait 连接池中连接用完时,新的请求等待时间,毫秒         username 数据库用户名        password 数据库密码        -->    <Resource name="jdbc/mysqlds"         auth="Container"         type="javax.sql.DataSource"         username="root"         password="root"         maxIdle="30"         maxWait="10000"         maxActive="100"        driverClassName="com.mysql.jdbc.Driver"        url="jdbc:mysql://127.0.0.1:3306/db_blog" />

配置好后需要注意的两个步骤:
1.将对应数据库的驱动类放到tomcat的lib目录下
2.重新启动tomcat服务器,让配置生效
在web应用程序的web.xml中设置数据源参考,如下:
在web-app节点中加入下面内容

<resource-ref>      <description>mysql数据库连接池</description>      <!-- 参考数据源名字,同Tomcat中配置的Resource节点中name属性值"jdbc/mysqlds"一致 -->      <res-ref-name>jdbc/mysqlds</res-ref-name>      <!-- 资源类型 -->      <res-type>javax.sql.DataSource</res-type>      <!-- 权限 -->      <res-auth>Container</res-auth>      <res-sharing-scope>Shareable</res-sharing-scope></resource-ref>

在Web应用中使用数据源

try {                  //初始化查找命名空间            Context ctx = new InitialContext();              //参数java:/comp/env为固定路径               Context envContext = (Context)ctx.lookup("java:/comp/env");             //参数jdbc/mysqlds为数据源和JNDI绑定的名字            DataSource ds = (DataSource)envContext.lookup("jdbc/mysqlds");             Connection conn = ds.getConnection();                 conn.close();                 out.println("<span style='color:red;'>JNDI测试成功<span>");             } catch (NamingException e) {                 e.printStackTrace();             } catch (SQLException e) {                 e.printStackTrace();             }     

方法二、在Tomcat的conf/server.xml中配置虚拟目录时配置
在配置虚拟目录时,也就是在配置conf下面的server.xml时,在context标签内添加池配置.在说该方法之前,先说一下,如何用tomcat配置虚拟目录。在tomcat\conf下server.xml中找到

<Host name="localhost"  appBase="webapps"            unpackWARs="true" autoDeploy="true"            xmlValidation="false" xmlNamespaceAware="false"></Host>

在其中添加:

<Context path="/website" docBase="F:/myweb" reloadable="true"></Context>

注意:
docBase要改成你的项目目录。
path为虚拟路径,访问时的路径,注意:一定要加“/” debug建议设置为0
reloadable设置为true。
这样重新启动tomcat
实例中如下配置

<Context path="/website" docBase="D:/program files/Tomcat/apache-tomcat-6.0.33/webapps/iblog.war" reloadable="true"></Context>

接下来添加池配置,如下

<!--配置虚拟目录--><Context path="/website" docBase="D:/program files/Tomcat/apache-tomcat-6.0.33/webapps/iblog.war" reloadable="true">            <Resource name="jdbc/mysqlds"             auth="Container"             type="javax.sql.DataSource"             username="root"             password="root"             maxIdle="30"             maxWait="10000"             maxActive="100"            driverClassName="com.mysql.jdbc.Driver"            url="jdbc:mysql://127.0.0.1:3306/db_blog"            /></Context>

方法三、在Web项目中的META-INF目录下新建一个文件context.xml,写入配置
注意:是META-INF目录下,不是WEB-INF目录下

<?xml version='1.0' encoding='utf-8'?><Context>    <Resource name="jdbc/mysqlds"         auth="Container"         type="javax.sql.DataSource"         username="root"         password="root"         maxIdle="30"         maxWait="10000"         maxActive="100"        driverClassName="com.mysql.jdbc.Driver"        url="jdbc:mysql://127.0.0.1:3306/db_blog"        logAbandoned="true" /></Context>

方法四、在Tomcat的conf/server.xml中配置
打开tomcat的conf/server.xml文件,找到GlobalNamingResources节点,默认的内容如下

<GlobalNamingResources>    <Resource name="UserDatabase" auth="Container"              type="org.apache.catalina.UserDatabase"              description="User database that can be updated and saved"              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"              pathname="conf/tomcat-users.xml" /></GlobalNamingResources>

在该节点中加入相关的池配置信息,如下

 <GlobalNamingResources>             <Resource name="UserDatabase" auth="Container"              type="org.apache.catalina.UserDatabase"              description="User database that can be updated and saved"              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"              pathname="conf/tomcat-users.xml" />             <!--配置mysql数据库的连接池,                 需要做的额外步骤是将mysql的Java驱动类放到tomcat的lib目录下                       -->             <Resource name="jdbc/mysqlds"               auth="Container"               type="javax.sql.DataSource"               username="root"               password="root"               maxIdle="30"               maxWait="10000"               maxActive="100"              driverClassName="com.mysql.jdbc.Driver"              url="jdbc:mysql://127.0.0.1:3306/db_blog" />  </GlobalNamingResources>

在tomcat的conf/context.xml文件中的节点中加入如下内容

<ResourceLink name="jdbc/mysqlds" global="jdbc/mysqlds" type="javax.sql.DataSource"/>

然后在web项目中的WEB-INF目录下的web.xml中配置

<resource-ref>      <description>mysql数据库连接池</description>      <!-- 参考数据源名字,同Tomcat中配置的Resource节点中name属性值"jdbc/mysqlds"一致 -->      <res-ref-name>jdbc/mysqlds</res-ref-name>      <!-- 资源类型 -->      <res-type>javax.sql.DataSource</res-type>      <res-auth>Container</res-auth>      <res-sharing-scope>Shareable</res-sharing-scope></resource-ref>

同样配置好后,需要重新启动服务器,让配置生效.

原创粉丝点击