1. 连接池相关技术调研
1.1. 池化技术
1.1.1. 池化技术概述
池化是一种通过复用来提升软件系统性能的的软件技术。
其原理是,通过复用对象来减少创建对象、垃圾回收的开销,这样能够减少资源对象的创建次数,提高程序的性能,特别是在高并发下这种提高更加明显。
使用池化技术缓存的资源对象有如下共同特点:
- 对象创建时间长
- 对象创建需要大量资源
- 对象创建后可被重复使用
池化技术应用:
- 线程池
- JDK中ThreadPoolExecutor
- Tomcat中的线程池
- 内存池
- 连接池
- HttpClient连接池
- JDBC连接池 (C3P0、BoneCP、DBCP等)
- Redis 连接池 (jedis)
- 等等
1.1.2. commons-pool2 包
commons-pool2是一个广泛使用的对象池组件,由apache基金会开源,当前最新版本是Version 2.8.0
核心类:
- PooledObjectFactory:工厂类,负责具体对象的创建、初始化,对象状态的销毁和验证
- ObjectPool:实现对对象存取和状态管理的池实现;如:线程池、数据库连接池
- PooledObject:池化对象,是需要放到ObjectPool对象的一个包装类。添加了一些附加的信息,比如说状态信息,创建时间,激活时间,关闭时间等
ObjectPool的核心数据结构:
* private final Map<T, PooledObject<T>> allObjects 存储所有的对象(不含销毁的对象)
* private final LinkedBlockingDeque<PooledObject<T>> idleObjects 后者用于存储空闲的对象,供borrow
// commons-pool2的使用demo
public static void main(String[] args) {
// 创建池对象工厂
PooledObjectFactory<Resource> factory = new MyPoolableObjectFactory();
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 最大空闲数
poolConfig.setMaxIdle(5);
// 最小空闲数
poolConfig.setMinIdle(1);
// 最大池对象总数
poolConfig.setMaxTotal(20);
// 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
poolConfig.setMinEvictableIdleTimeMillis(1800000);
// 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
poolConfig.setTimeBetweenEvictionRunsMillis(1800000 * 2L);
// 在获取对象的时候检查有效性, 默认false
poolConfig.setTestOnBorrow(true);
// 在归还对象的时候检查有效性, 默认false
poolConfig.setTestOnReturn(false);
// 在空闲时检查有效性, 默认false
poolConfig.setTestWhileIdle(false);
// 最大等待时间, 默认的值为-1,表示无限等待。
poolConfig.setMaxWaitMillis(5000);
// 是否启用后进先出, 默认true
poolConfig.setLifo(true);
// 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
poolConfig.setBlockWhenExhausted(true);
// 每次逐出检查时 逐出的最大数目 默认3
poolConfig.setNumTestsPerEvictionRun(3);
// 创建对象池
final GenericObjectPool<Resource> pool = new GenericObjectPool<Resource>(factory, poolConfig);
for (int i = 0; i < 21; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 注意,如果对象池没有空余的对象,那么这里会block,可以设置block的超时时间
Resource resource = pool.borrowObject();
System.out.println(resource);
Thread.sleep(3000);
pool.returnObject(resource);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
1.1.3. Alibaba-Druid
阿里巴巴数据库事业部出品,为监控而生的数据库连接池。号称是Java语言中最好的数据库连接池,能够提供强大的监控和扩展功能。
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。
同时Druid不仅仅是一个数据库连接池,它包括三个部分:
- 基于Filter-Chain模式的插件体系。
- DruidDataSource 高效可管理的数据库连接池。
- SQLParser
Druid的功能:
- 替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
- 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
- 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。
- SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。
- 扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。