Java 数据持久化系列之池化技术

本文深入探讨了池化技术的重要性,特别是针对数据库连接对象。通过使用Apache Common Pool2实现了一个简单的数据库连接池,并进行性能测试。文章分析了Pool2的源码,了解对象状态变化及管理过程,为理解高性能数据库连接池如HikariCP和Druid奠定了基础。
摘要由CSDN通过智能技术生成

今天我们就先来了解一下池化技术的必要性、原理;然后使用 Apache-common-Pool2实现一个简单的数据库连接池;接着通过实验,对比简单连接池、HikariCP、Druid 等数据库连接池的性能数据,分析实现高性能数据库连接池的关键;最后分析 Pool2 的具体源代码实现。

图片

对象不是你想要,想要就能要

你我单身狗们经常调侃可以随便 New 出一个对象,用完就丢。但是有些对象创建的代价比较大,比如线程、tcp连接、数据库连接等对象。对于这些创建耗时较长,或者资源占用较大(占据操作系统资源,比如说线程,网络连接等)的对象,往往会引入池化来管理,减少频繁创建对象的次数,避免创建对象时的耗时,提高性能。

我们就以数据库连接 Connection 对象为例,详细说明一下创建该对象花费的时间和资源。下面是MySQL Driver 创建 Connection 对象的方法,在调用 connect 方法创建 Connection 时,会与 MySQL 进行网络通讯,建立 TCP 连接,这是极其消耗时间的。

 
  1. connection = driver.connect(URL, props);

使用 Apache-Common-Pool2实现简易数据库连接池

下面,我们以 Apache-Common-Pool2为例来看一下池化技术相关的抽象结构。

首先了解一下Pool2中三元一体的 ObjectPool,PooledObject 和 PooledObjectFactory,对他们的解释如下:

  • ObjectPool 就是对象池,提供了 borrowObject 和 returnObject 等一系列函数。

  • PooledObject 是池化对象的封装类,负责记录额外信息,比如说对象状态,对象创建时间,对象空闲时间,对象上次使用时间等。

  • PooledObjectFactory 是负责管理池化对象生命周期的工厂类,提供 makeObject, destroyObject, activateObject 和 validateObject 等一系列函数。

上述三者都有其基础的实现类,分别是 GenericObjectPool,DefaultPooledObject 和 BasePooledObjectFactory。上一节实验中的 SimpleDatasource 就是使用上述类实现的。

首先,你要实现一个继承 BasePooledObjectFactory 的工厂类,提供管理池化对象生命周期的具体方法:

  • makeObject:创建池化对象实例,并且使用 PooledObject 将其封装。

  • validateObject:验证对象实例是否安全或者可用,比如说 Connection 是否还保存连接状态。

  • activateObject:将池返回的对象实例进行重新初始化,比如说设置 Connection是否默认AutoCommit等。

  • passivateObject:将返回给池的对象实例进行反初始化,比如说 Connection 中未提交的事务进行 Rollback等。

  • destroyObject:销毁不再被池需要的对象实例,比如说 Connection不再被需要时,调用其 close 方法。

具体的实现源码如下所示,每个方法都有详细的注释。

 
  1. public class SimpleJdbcConnectionFactory extends BasePooledObjectFactory<Connection> {

  2. ....

  3. @Override

  4. public Connection create() throws Exception {

  5. // 用于创建池化对象

  6. Properties props = new Properties();

  7. props.put("user", USER_NAME);

  8. props.put("password", PASSWORD);

  9. Connection connection = driver.connect(URL, props);

  10. return connection;

  11. }

  12. @Override

  13. public PooledObject<Connection> wrap(Connection connection) {

  14. // 将池化对象进行封装,返回DefaultPooledObject,这里也可以返回自己实现的PooledObject

  15. return new DefaultPooledObject<>(connection);

  16. }

  17. @Override

  18. public PooledObject<Connection> makeObject() throws Exception {

  19. return super.makeObject();

  20. }

  21. @Override

  22. public void destroyObject(PooledObject<Connection> p) throws Exception {

  23. p.getObject().close();

  24. }

  25. @Override

  26. public boolean validateObject(PooledObject<Connection> p) {

  27. // 使用 SELECT 1 或者其他sql语句验证Connection是否可用,ConnUtils代码详见Github中的项目

  28. try {

  29. ConnUtils.validateConnection(p.getObject(), this.validationQuery);

  30. } catch (Exception e) {

  31. return false;

  32. }

  33. return true;

  34. }

  35. @Override

  36. public void activateObject(PooledObject<Connection> p) throws Exception {

  37. Connection conn = p.getObject();

  38. // 对象被借出,需要进行初始化,将其 autoCommit进行设置

  39. if (conn.getAutoCommit() != defaultAutoCommit) {

  40. conn.setAutoCommit(defaultAutoCommit);

  41. }

  42. }

  43. @Override

  44. public void passivateObject(PooledObject<Connection> p) throws Exception {

  45. // 对象被归还,进行回收或者处理,比如将未提交的事务进行回滚

  46. Connection conn = p.getObject();

  47. if(!conn.getAutoCommit() &a

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值