JavaWeb-JDBC-数据连接池

来源:互联网 发布:sybase数据库12.5 编辑:程序博客网 时间:2024/06/06 09:26

话说:
前面注重简单的CURD功能的实现,今天来总结下连接池。

Why?
我们每次访问页面,页面请求被后端捕获后,后台代码访问数据库,按照我们之前代码的方式,页面每请求一次,后端就连接一次,从数据库取数据,也就是调用我们的getConn()方法。一旦用户多起来,直接会造成数据库服务器的宕机或者页面卡死状态,怎么搞定?假如类似双11那样的访问量呢…….

What?

连接池
就是用来解决以上问题的一种方案。顾名思义,连接池是个数据池子,可以存放多个连接,供用户发起请求的时候直接从池子里面取值,而不是每次都访问数据库服务器。这样的话,大大提高了效率,如果一次访问次数多余连接池初始化数量,那么就有排队机制处理,等其他用户释放资源以后,在获取连接。
常见的数据连接池技术有:c3p0 dbcp druid 等等
既然是对JDBC连接的优化和补充,所以整体连接方式大同小异。

目录


一、c3p0
二、dbcp
三、druid


一、c3p0

1、根据文档配置,连接模式和链接JDBC神似。
http://www.mchange.com/projects/c3p0/
C3P0的API:
http://www.mchange.com/projects/c3p0/apidocs/index.html
导入c3p0-0.9.2.1.jar
mchange-commons-java-0.2.3.4.jar
新建一个类(TestC3P0Conn)来测试:

package com.hmc.datasource;import com.mchange.v2.c3p0.ComboPooledDataSource;import java.beans.PropertyVetoException;import java.sql.SQLException;/** * User:Meice * 2017/10/6 */public class TestC3P0Conn {    public static void main(String[] args) {        ComboPooledDataSource cpds = new ComboPooledDataSource();        try {                cpds.setDriverClass("com.mysql.jdbc.Driver");//loads the jdbc driver                cpds.setJdbcUrl("jdbc:mysql://localhost:3306/news_db");                cpds.setUser("root");                cpds.setPassword("119913");                //设置连接池初始化大小                cpds.setInitialPoolSize(300);                //设置连接池最大大小                cpds.setMaxPoolSize(1000);                long start = System.currentTimeMillis();                for(int i=1;i<=200;i++) {                     cpds.getConnection();                }                 long end = System.currentTimeMillis();            System.out.println("共耗时:"+(end-start)+"毫秒");        } catch (PropertyVetoException e) {            e.printStackTrace();        } catch (SQLException e) {            e.printStackTrace();        }        // cpds.close(); //close the connection    }}

同样,我们也用JDBC连接来测试做对比:

package com.hmc.datasource;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;/** * User:Meice * 2017/10/6 */public class TestCommonConn {    public static  void main(String[] args) {        try {            //开始计时            long start = System.currentTimeMillis();            //注册驱动            Class.forName("com.mysql.jdbc.Driver");            //模拟很多用户连接            for(int i=1;i<=300;i++) {                //获取连接                Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/news_db",                        "root", "119913");            }            long end = System.currentTimeMillis();            System.out.println("共耗时:"+(end-start)+"毫秒");        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (SQLException e) {            e.printStackTrace();        }    }}

总结:


上面两种连接方式种,我们改变循环次数,查看连接时间(毫秒);在连接C3P0的时候,把连接池初始化大小、连接池最大连接数量轮流作为变量,调整,观察连接时间。
发现,JDBC连接循环300次,直接报错。

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: “Too many connections”

C3P0也是一样。当然这样初步测试连接时间,不够精确,有专门的测试工具.

实际有运用呢?
1、对于连接池而言,初始化值越大,那么启动速度越慢,访问速度越快;
反之亦然。
2、实践中,我们分为开发环境和生产环境。开发环境时,初始化一般设置小一些,生产环境列?不能想当然设计,要根据业务访问量来灵活设置。
3、同样,连接池还可以用来监测访问量大小。


二、DBCP

官网学习资料:
http://commons.apache.org/proper/commons-dbcp/guide/jndi-howto.html
同样,也是需要包,导入这几个。
commons-dbcp-1.4.jar
commons-logging-1.1.1.jar
commons-pool-1.5.4.jar
代码如下:

package com.hmc.datasource;import org.apache.commons.dbcp.BasicDataSource;import java.sql.Connection;import java.sql.SQLException;/** * User:Meice * 2017/10/6 */public class TestDBCPConn {    public static void main(String[] args) {        BasicDataSource bds= new BasicDataSource();        bds.setDriverClassName("com.mysql.jdbc.Driver");        bds.setUrl("jdbc:mysql://localhost:3306/news_db");        bds.setUsername("root");        bds.setPassword("119913");        bds.setInitialSize(300);        long start = System.currentTimeMillis();        try {            for(int i=1;i<=200;i++) {               Connection conn = bds.getConnection();               conn.close();            }            long end = System.currentTimeMillis();            System.out.println("共耗时:"+(end-start)+"毫秒");        } catch (SQLException e) {            e.printStackTrace();        }    }}

我们可以反复调整循环次数,来对比运行效率。因为我们这个是单线程,测试不是很有意义。其实最贴切的应该用多线程来实现并发访问,这样测算连接效率最好。

测试了下,当然当做玩玩啦。

这里写图片描述

网上有专业的对比,大家可以参考,那个有意义,笔者这个只是小打小闹,单线程的。

https://github.com/alibaba/druid/wiki/linux-benchmark

三、druid

参考链接
http://www.iteye.com/magazines/90
API:http://static.druid.io/api/0.10.1/
包:druid-1.0.9.jar
更多详细内容可以参考:

http://www.cnblogs.com/niejunlei/p/597795.html
这里写图片描述

这里温习一下之前的properties
我们在src目录下新建一个druid.properties的文件,做配

driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/news_dbuser=rootpassword=119913

写一个类:JavaDruidConn

package com.hmc.datasource;import com.alibaba.druid.pool.DruidDataSource;import com.alibaba.druid.pool.DruidDataSourceFactory;import com.alibaba.druid.pool.DruidPooledConnection;import com.alibaba.druid.util.DruidDataSourceUtils;import java.io.IOException;import java.io.InputStream;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;/** * User:Meice * 2017/10/6 */public class TestDruidConn {    DruidDataSource dds = null;    //获取配置数据源,封装为一个方法    public DruidDataSource getDataSource() throws Exception {        //以下代码加载配置文件,不在赘述        Properties pro = new Properties();        InputStream is = this.getClass().getClassLoader().getResourceAsStream("druid.properties");        pro.load(is);       String user =  pro.getProperty("url");       System.out.println(user);        dds = (DruidDataSource) DruidDataSourceFactory.createDataSource(pro);        return  dds;    }    //获取连接方法    public DruidPooledConnection getDruidPooledConnection(DruidDataSource dds ) throws SQLException {        dds.setAccessToUnderlyingConnectionAllowed(true);        DruidPooledConnection dpc = dds.getConnection();        return  dpc;    }    public static void main(String[] args){        try {            //测试连接         TestDruidConn tdc =   new TestDruidConn();         DruidDataSource dds = tdc.getDataSource();            Connection conn = tdc.getDruidPooledConnection(dds);        } catch (Exception e) {            e.printStackTrace();        }    }}

不过,测试有问题。暂未找到答案,所以druid测试仅仅作为自己的一个测试记录。

原创粉丝点击