开发者社区> 青衫无名> 正文

数据库连接池clearpool(java实现)详解

简介:
+关注继续查看

clearpool的maven项目托管在https://github.com/xionghuiCoder/clearpool,同时也可以在http://www.oschina.net/p/clearpool上了解它的简单介绍。

首先大家可能会问,现在开源社区已经有了很多数据库连接池:c3p0、proxool、dbcp、bonecp、druid和tomcat_jdbc等,我们还需要重新发明轮子么?是的,上面这些连接池都非常优秀,并且都有自己优点:比如高并发时druid和tomcat_jdbc近乎完美的性能,再比如proxool和druid的监控功能;然而它们并不是完美的,比如性能是否还能再提升、如何管理分布式数据库、如何支持分布式事务。好的,下面就来介绍下clearpool以及它是如何支持这些功能的。

1、如何使用clearpool

clearpool提供的接口类为ClearPoolDataSource.java,它支持两种配置方法:配置xml、ioc注入(或者编程实现):xml的详细配置信息请参考https://github.com/xionghuiCoder/clearpool/tree/master/src/main/java/org/opensource/clearpool/configuration/example下面的三个示例。

这里说下clearpool和其它数据库池的不同的地方:

1)它放弃了最小连接池数(min-pool-size),取而代之的是核心连接池数(core-pool-size):个人认为min-pool-size没什么用处;

2)它不提供返回真实连接的方法,ClearPoolDataSource.java的getConnection()方法返回的是数据库连接的代理,除非利用反射机制(不建议这么做),不然不能真正操作数据库连接;这么做的原因请参考3);

3)它不会在获取连接时测试连接是否有效,因为这个操作可能会非常耗时(比如需要远程调用);这是因为它并不会返回真实的连接,所以就不用担心会不小心关闭连接等意外情况。

2、如何配置DataSource

clearpool提供三种数据源配置方式:

1)配置JDBC,请参考clearpool-jdbc.xml的标签;

2)配置jndi,请参考clearpool-jndi.xml的标签;

3)如果是自定义的DataSource,可以使用DataSourceHolder.java的setDataSourceMap()方法来配置(key为数据库池名称,和一致,value为DataSource);

clearpool支持三种数据源:ConnectionPoolDataSource、XADataSource和DataSource。

如果需要支持分布式事务则需要配置XADataSource或者支持XA协议的JDBC。

3、clearpool的性能

根据测试结果:druid和tomcat_jdbc的性能是非常优秀的,在某些高并发的情况下它俩的性能要比其它的连接池高上十倍甚至是几十倍。然而他们无一例外地都使用了连接池锁(proxool未使用锁,在高并发的情况下获取连接会导致ArrayIndexOutOfBoundsException),那么如果我们不使用锁的话那岂不是能提高性能?是的,这是当然。clearpool在获取连接时没有使用任何锁机制,而且不会导致任何异常,它的秘诀是使用Atomic操作代替了锁,详细的实现清参考类https://github.com/xionghuiCoder/clearpool/blob/master/src/main/java/org/opensource/clearpool/core/chain/AtomicSingleChain.java。然而AtomicSingleChain.java用到了sun.misc.Unsafe.java,或许比较保守的人会说这是一种冒险的做法;是的,或许以后某天oracle会抛弃Unsafe.java;不过没关系,这时我们可以使用AtomicSingleChain.java的替身LockSingleChain.java,这是一个普通的、使用锁的连接池实现。下图显示了clearpool和druid、tomcat_jdbc的性能比较结果(最大连接数为50、核心连接数为20、线程数为100):

image

上图的测试结果来自于:https://github.com/xionghuiCoder/clearpool/blob/master/src/test/java/org/opensource/clearpool/CompareWithWonderfulPool.java,如果想了解和其它数据库的性能比较结果请运行测试类:https://github.com/xionghuiCoder/clearpool/blob/master/src/test/java/org/opensource/clearpool/CompareWithPopularPool.java

上图比较的是高并发下“获取连接”时的性能,如果需要测试高并发下的DML,clearpool的性能就和druid、tomcat_jdbc差不多了,原因在于clearpool使用动态代理生成Statement代理,而动态代理生成字节码时会比较耗时,并且会作为WeakReference缓存,而高并发下会多次启动gc,所以会多次回收并多次生成字节码,所以就影响了测试结果(详细原理请参考JDK的java.lang.reflect.Proxy.java的源码)。而druid和tomcat_jdbc使用的是普通的代理,所以没有这个问题。clearpool使用动态代理的原因主要是为了减少代码量(我是个懒人),如果使用静态代理,至少需要实现三个代理类(Statement、PreparedStatement和CallableStatement)以及它们的所有方法。而使用动态代理只需要一个handler(https://github.com/xionghuiCoder/clearpool/blob/master/src/main/java/org/opensource/clearpool/datasource/proxy/dynamic/StatementHandler.java)就足够了。

4、管理分布式数据库池和JTA

clearpool可以管理分布式数据库,配置分布式连接池时我们需要做的是配置多个标签(xml配置)或者初始化多个连接池(IOC或者编程实现)。clearpool会根据配置自动管理所有连接池:比如多余空闲连接的回收、无效连接的重置、数据库池的监控等等。clearpool还提供了支持JTA的接口类:UserTransactionImpl.java,我们可以像下面这样使用分布式事务(con1和con2取自数据库连接池):

**UserTransaction tx = new UserTransactionImpl();
Statement st1 = con1.createStatement();
Statement st2 = con2.createStatement();
tx.begin();
try{

st1.execute(“insert**”);     
st2.execute(“update**”);     
tx.commit();     

}catch(Throwable t){

tx.rollback();     

}**

5、如何监控数据库连接池

clearpool通过JMX来实现数据库池的监控功能,而druid和proxool则是使用servlet实现;然而JMX的可编程性并没有servlet好,这里放弃servlet是考虑到可能有的用户并不需要web容器,如果为了监控数据库池而让他们专门搭建个web环境是不公平的。

如果想要使得clearpool监控数据库连接池,则需要配置(xml配置)或者设置ClearPoolDataSource的Console字段,我们可以通过的配置端口、通过的配置用户名和密码,详细监控功能可参考测试用例https://github.com/xionghuiCoder/clearpool/blob/master/src/test/java/org/opensource/clearpool/UniqueFunction.java。下面是监控页面的部分截图:

image

如果需要打印sql,则需要配置为true或者设置ClearPoolDataSource的setShowSql()方法,同时需要启用日志功能(classpath中加入commons-logging.jar即可),下面是查询代码、打印的sql和sql耗时的截图:

PreparedStatement stmt = conn.prepareStatement("select 1 from geek where name=? and age=?");
stmt.setString(1, "Bill Joy");
stmt.setInt(2, 60);
stmt.execute();
stmt.close();

image

6、如何加密数据库密码

如果想要加密配置文件中的数据库密码,可以参考如下配置:

<jdbc>
    <jdbc-class>org.opensource.clearpool.util.MockTestDriver</jdbc-class>
    <url>jdbc:mock:case</url>
    <user>1</user>
    <password>1</password>
    <security-class>org.opensource.clearpool.security.SecretAES</security-class>
    <file-path>path</file-path>
    <status>encrypt</status>
</jdbc>

为加密和解密的处理类(可以不设置,默认会使用SecretAES),如果设置它,则需要实现接口org.opensource.clearpool.security.Secret.java;Secret接口有两个方法:encrypt(String)进行加密,decrypt(String)进行解密。

为该配置文件的绝对路径(请将里面的path替换为配置文件的真正路径),加密密码后会根据该路径来重置密码;如果为encrypt则需要配置,否则不需要。

表示的状态:有效取值为encrypt和decrypt;encrypt表示需要加密(加密密码后会重置为decrypt),decrypt表示需要解密。

下图为加密后的xml:

<jdbc>
    <jdbc-class>org.opensource.clearpool.util.MockTestDriver</jdbc-class>
    <url>jdbc:mock:case</url>
    <user>1</user>
    <password>WDroom5uAqkPfQwgOMCQGQ==</password>
    <security-class>org.opensource.clearpool.security.SecretAES</security-class>
    <file-path>path</file-path>
    <status>decrypt</status>
</jdbc>

另外啰嗦两句:数据库密码加密功能有点儿掩耳盗铃的感觉,因为最终数据库的配置信息都会保存在connection的实现类的字段中,所以可以通过反射来获取密码(我尝试过oracle驱动和mysql驱动,都可以获取密码,没试过sqlserver驱动,不过应该也一样)。所以数据库密码加密只能防止用户直接从配置文件内获取密码。

7、其它

clearpool可以打印日志,然而并不提供log的任何实现,它并不像proxool那样强制把commons-logging.jar的代码内嵌入proxool.jar,这样耦合性太强了,考虑下如果commons-logging发布了新版本怎么办;而clearpool能够和commons-logging无缝衔接,如果需要日志功能则只需要把commons-logging.jar加入到classpath中。好吧,“clearpool并不生产日志,它只是日志的搬运工”。clearpool代码量十分地少,jar包只有75KB左右,非常易于使用,相信你能非常快地使用和修改它。

PS:clearpool支持JDK6和JDK7。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java实现单词计数MapReduce
本文分享实现单词计数MapReduce的方法
91 0
JAVA 实现上传图片添加水印(详细版)(上)
JAVA 实现上传图片添加水印(详细版)
168 0
Java 实现汉字按照首字母分组排序
Java 实现汉字按照首字母分组排序
113 0
Java实现图书管理系统
本篇文章是对目前Java专栏已有内容的一个总结练习,希望各位小主们在学习完面向对象的知识后,可以阅览本篇文章后,自己也动手实现一个这样的demo来加深总结应用已经学到知识并进行巩固。
130 0
java实现spring boot项目启动时,重启Windows进程
java实现spring boot项目启动时,重启Windows进程
159 0
Java实现拼图小游戏(1)—— JFrame的认识及界面搭建
如果要在某一个界面里面添加功能的话,都在一个类中,会显得代码难以阅读,而且修改起来也会很困难,所以我们将游戏主界面、登录界面、以及注册界面都单独编成一个类,每一个类都继承JFrame父类,并且在类中创建方法来来实现页面
108 0
Java网络编程:UDP/TCP实现实时聊天、上传图片、下载资源等
ip地址的分类: 1、ipv4、ipv6 127.0.0.1:4个字节组成,0-255,42亿;30亿都在北美,亚洲就只有4亿 2011年就用尽了。
96 0
Java实现拼图小游戏(7)—— 计步功能及菜单业务的实现
注意由于我们计步功能的步数要在重写方法中用到,所以不能将初始化语句写在方法体内,而是要写在成员位置。在其名字的时候也要做到“见名知意”,所以我们给它起名字为step
69 0
Java实现拼图小游戏(7)—— 作弊码和判断胜利
当我们好不容易把拼图复原了,但是一点提示也没有,完全看不出来是成功了,那么我们就需要有判断胜利的功能去弹出“成功”类的图片,以便于玩家选择是重新开始还是退出小游戏
69 0
Java实现拼图小游戏(7)——查看完整图片(键盘监听实例2)
由于在移动和图片中我们已经添加了键盘监听,也继承了键盘监听的接口,那么我们只需要在重写方法内输入我们的代码即可
41 0
+关注
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Java工程师必读手册
立即下载
Java应用提速(速度与激情)
立即下载
Java单元测试实战
立即下载