commons-pool与commons-pool2连接池
commons-pool和commons-pool2是用来建立对象池的框架,提供了一些将对象池化必须要实现的接口和一些默认动作。对象池化之后可以通过pool的概念去管理其生命周期,例如对象的创建,使用,销毁等。例如我们通常使用的连接池,连接池可以有效管理连接的数量和状态,保证连接资源的情况而且避免并发场景下连接的频繁建立和释放。
我们这里来讲述如何使用commons-pool2来池化对象。我们以池化hadoop连接为例。
1、先解决依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.3</version>
</dependency>
2、如何使用连接池
我们是在spingboot框架中池化hadoop集群连接,先看一下池化之后的效果。
下面是我们池化之后的hadoop集群客户端。可以看到我们可以通过连接池的方式管理hadoo集群的链接。
1)配置连接池
最大连接数maxTotal
最大空闲连接数maxIdle
最小空闲连接数minIdle
获取连接的最大等待时间maxWait
可以看到传入这些配置的时候我们使用了一个config对象JHadoopPoolConfig,后面我们将说明这个config对象如何实现。
2)管理连接池
我们以三个函数说明了如何去连接池中申请连接,使用连接和释放链接资源。
申请资源pool.getResource()
释放资源pool.returnBrokenResource()和pool.returnResource()
这里要注意的是,一定要在catch和finally中成功释放资源,不然会导致could not get a Resource from the Pool的异常
package com.xiaoju.dqa.jazz.hadoop.client;
import org.apache.hadoop.fs.FileStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.SimpleDateFormat;
import java.util.Date;
public class JHadoopClient {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private JHadoopPool jHadoopPool;
private String coreResource;
private String hdfsResource;
private int maxTotal;
private int maxIdle;
private int minIdle;
private int maxWaitMillis;
public String getCoreResource() {
return coreResource;
}
public void setCoreResource(String coreResource) {
this.coreResource = coreResource;
}
public String getHdfsResource() {
return hdfsResource;
}
public void setHdfsResource(String hdfsResource) {
this.hdfsResource = hdfsResource;
}
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public int getMaxWaitMillis() {
return maxWaitMillis;
}
public void setMaxWaitMillis(int maxWaitMillis) {
this.maxWaitMillis = maxWaitMillis;
}
public int getMinIdle() {
return minIdle;
}
public void setMinIdle(int minIdle) {
this.minIdle = minIdle;
}
public void init() {
try {
JHadoopPoolConfig conf = new JHadoopPoolConfig();
conf.setMaxTotal(maxTotal);
conf.setMaxIdle(maxIdle);
conf.setMinIdle(minIdle);
conf.setMaxWaitMillis(maxWaitMillis);
jHadoopPool = new JHadoopPool(conf, coreResource, hdfsResource);
logger.info("[HDFS]初始化JHadoopClient成功");
} catch (Exception ex) {
logger.error("[HDFS]初始化JHadoopClient失败", ex);
}
}
public void stop() {
try {
jHadoopPool.destroy();
} catch(Exception e) {
}
}
public boolean exists(String path) throws Exception {
JHadoop jHadoop = null;
boolean broken = false;
try {
jHadoop = jHadoopPool.getResource();
return jHadoop.exists(path);
} catch (Exception e) {
broken = true;
jHadoopPool.returnBrokenResource(jHadoop);
logger.error("[HDFS]判断文件是否存在失败", e);
throw e;
} finally {
if (null != jHadoop && !broken) {
jHadoopPool.returnResource(jHadoop);
}
}
}
public String getModificationTime(String path) throws Exception {
JHadoop jHadoop = null;
boolean broken = false;
try {
jHadoop = jHadoopPool.getResource();
FileStatus fileStatus = jHadoop.getFileStatus(path);
long modifyTimestamp = fileStatus.getModificationTime();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date(modifyTimestamp);
return simpleDateFormat.format(date);
} catch (Exception e) {
broken = true;
jHadoopPool.returnBrokenResource(jHadoop);
logger.error("[HDFS]获取最近修改时间失败", e);
throw e;
} finally {
if (null != jHadoop && !broken) {
jHadoopPool.returnResource(jHadoop);
}
}
}
public long getPathSize(String path) throws Exception {
JHadoop jHadoop = null;
boolean broken = false;
try {
jHadoop = jHadoopPool.getResource();
return jHadoop.getContentSummary(path).getLength();
} catch (Exception e) {
broken = true;
jHadoopPool.returnBrokenResource(jHadoop);
logger.error("[HDFS]获取路径大小失败", e);
throw e;
} finally {
if (null != jHadoop && !broken) {
jHadoopPool.returnResource(jHadoop);
}
}
}
}
3)注册成bean
通过配置文件传入链接池相应的配置。
package com.xiaoju.dqa.jazz.hadoop.configuration;
import com.xiaoju.dqa.jazz.hadoop.client.JHadoopClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HadoopConfig {
@Value("${hadoop.core.resource}")
private String coreResource;
@Value("${hadoop.hdfs.resource}")
private String hdfsResource;
@Value("${hadoop.pool.maxTotal}")
private int maxTotal;
@Value("${hadoop.pool.maxIdle}")
private int maxIdle;
@Value("${hadoop.pool.minIdle}")
private int minIdle;
@Value("${hadoop.pool.maxWaitMillis}")
private int maxWaitMillis;
@Bean(initMethod = "init", destroyMethod = "stop")
public JHadoopClient jHadoopClient() {
JHadoopClient jHadoopClient = new JHadoopClient();
jHadoopClient.setMaxTotal(maxTotal);
jHadoopClient.setMaxIdle(maxIdle);
jHadoopClient.setMinIdle(minIdle);
jHadoopClient.setMaxWaitMillis(maxWaitMillis);
jHadoopClient.setCoreResource(coreResource);
jHadoopClient.setHdfsResource(hdfsResource);
return jHadoopClient;
}
}
4)config对象如何实现
我们这里要说明一下下面这些参数的含义:
1)setTestWhileConfig - 在空闲时检查有效性, 默认false
2)setMinEvictableIdleTimeMillis - 逐出连接的最小空闲时间
3)setTimeBetweenEvictionRunsMillis - 逐出扫描的时间间隔(毫秒) 如果为负数则不运行逐出线程,默认-1
4)setNumTestsPerEvictionRun - 每次逐出检查时 逐出的最大数目package com.xiaoju.dqa.jazz.hadoop.client;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class JHadoopPoolConfig extends GenericObjectPoolConfig {
public JHadoopPoolConfig() {
this.setTestWhileIdle(true);
this.setMinEvictableIdleTimeMillis(60000L);
this.setTimeBetweenEvictionRunsMillis(30000L);
this.setNumTestsPerEvictionRun(-1);
}
}
3、连接池JHadoopPool
这个类继承了Pool<JHadoop>,用来初始化连接池对象。而JHadoop是Pool要管理的连接对象。
可以看到JHadoopPool在初始化的时候传入了一个JHadoopFactory的实例。这个实例将会以工厂模式来创建实际的JHadoop
JHadoopPool代码
package com.xiaoju.dqa.jazz.hadoop.client;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class JHadoopPool extends Pool<JHadoop> {
public JHadoopPool(GenericObjectPoolConfig poolConfig, String coreResource, String hdfsResource) {
super(poolConfig, new JHadoopFactory(coreResource, hdfsResource));
}
public JHadoopPool(GenericObjectPoolConfig poolConfig) {
super(poolConfig, new JHadoopFactory());
}
}
Jhadoop代码
package com.xiaoju.dqa.jazz.hadoop.client;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class JHadoop {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private FileSystem fs;
private String coreResource;
private String hdfsResource;
public JHadoop(String coreResource, String hdfsResource) {
this.coreResource = coreResource;
this.hdfsResource = hdfsResource;
}
public String getCoreResource() {
return coreResource;
}
public void setCoreResource(String coreResource) {
this.coreResource = coreResource;
}
public String getHdfsResource() {
return hdfsResource;
}
public void setHdfsResource(String hdfsResource) {
this.hdfsResource = hdfsResource;
}
public void open() {
try {
Configuration conf = new Configuration();
conf.addResource(coreResource);
conf.addResource(hdfsResource);
fs = FileSystem.get(conf);
logger.info("[JHadoop]创建实例成功");
} catch (Exception e) {
logger.error("[JHadoop]创建实例失败", e);
}
}
public void close() {
try {
if (null != fs) {
fs.close();
logger.info("[JHadoop]关闭实例成功");
}
} catch(Exception e) {
logger.error("[JHadoop]关闭实例失败", e);
}
}
public boolean isConnected() throws IOException {
fs.exists(new Path("/forTest"));
return true;
}
public boolean exists(String path) throws IOException {
Path hdfsPath = new Path(path);
return fs.exists(hdfsPath);
}
public FileStatus getFileStatus(String path) throws IOException {
Path hdfsPath = new Path(path);
return fs.getFileStatus(hdfsPath);
}
public ContentSummary getContentSummary(String path) throws IOException {
ContentSummary contentSummary = null;
Path hdfsPath = new Path(path);
if (fs.exists(hdfsPath)) {
contentSummary = fs.getContentSummary(hdfsPath);
}
return contentSummary;
}
}
4、连接工厂类JHadoopFactory
JHadoopFactory这个类管理着连接对象的创建,销毁,验证等动作
package com.xiaoju.dqa.jazz.hadoop.client;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
public class JHadoopFactory implements PooledObjectFactory<JHadoop> {
private final String coreResource;
private final String hdfsResource;
public JHadoopFactory() {
this.coreResource = "core-site.xml";
this.hdfsResource = "hdfs-site.xml";
}
public JHadoopFactory(String coreResource, String hdfsResource) {
this.coreResource = coreResource;
this.hdfsResource = hdfsResource;
}
@Override
public PooledObject<JHadoop> makeObject() throws Exception {
JHadoop jHadoop = new JHadoop(coreResource, hdfsResource);
jHadoop.open();
return new DefaultPooledObject<JHadoop>(jHadoop);
}
@Override
public void destroyObject(PooledObject<JHadoop> pooledJHadoop) throws Exception {
JHadoop jHadoop = pooledJHadoop.getObject();
jHadoop.close();
}
@Override
public boolean validateObject(PooledObject<JHadoop> pooledJHadoop) {
JHadoop jHadoop = pooledJHadoop.getObject();
try {
return jHadoop.isConnected();
} catch (Exception e) {
return false;
}
}
@Override
public void activateObject(PooledObject<JHadoop> pooledObject) throws Exception {
}
@Override
public void passivateObject(PooledObject<JHadoop> pooledObject) throws Exception {
}
}
commons-pool与commons-pool2连接池的更多相关文章
- 转!数据库连接池概念、种类、配置(DBCP\C3P0\JndI与Tomact配置连接池)
数据库连接池概念.种类.配置(DBCP\C3P0\JndI与Tomact配置连接池) 一.DBCP 连接:DBCP 连接池是 Apache 软件基金组织下的一个开源连接池实现. 需要的 java 包c ...
- 对象池化技术 org.apache.commons.pool
恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率.Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以 ...
- DBCP连接池介绍
DBCP连接池介绍 ----------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 ...
- DBCP连接池原理分析及配置用法
DBCP连接池介绍 ----------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 ...
- 【转】DBCP连接池原理分析
---------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 JDBC 3. DB ...
- Tomcat 连接池详解
(转) JDBC 连接池 org.apache.tomcat.jdbc.pool 是Apache-Commons DBCP连接池的一种替换或备选方案. 那究竟为何需要一个新的连接池? 原因如下: Co ...
- 深入理解Spring Boot数据源与连接池原理
Create by yster@foxmail.com 2018-8-2 一:开始 在使用Spring Boot数据源之前,我们一般会导入相关依赖.其中数据源核心依赖就是spring‐boot‐s ...
- Spring Boot之默认连接池配置策略
注意:如果我们使用spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa “starters”坐标,Spring Boot将自动配置Hikari ...
- java通过代理创建Conncection对象与自定义JDBC连接池
最近学习了一下代理发现,代理其实一个蛮有用的,主要是用在动态的实现接口中的某一个方法而不去继承这个接口所用的一种技巧,首先是自定义的一个连接池 代码如下 import java.lang.reflec ...
- DBCP连接池原理分析(转载)
DBCP连接池介绍 ----------------------------- 目前 DBCP 有两个版本分别是 1.3 和 1.4. DBCP 1.3 版本需要运行于 JDK 1.4-1.5 ,支持 ...
随机推荐
- 启动springjar
java -jar cms-exporter-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:./config
- 字符编码笔记:ASCII,Unicode和UT…
字符编码笔记:ASCII,Unicode和UTF-8 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才 ...
- 软工+C(2017第1期) 题目设计、点评和评分
// 下一篇:分数和checklist 如何设计题目 教学中的一个问题是老师出题太简单了,题目设计一开始上来就不紧凑,我认为一个好的课程应该上来就给你紧凑感,而不是先上来"轻松2-3周&qu ...
- Swing-JOptionPane对话框用法-入门
对话框是GUI程序中常见的界面,通常用来反馈提示信息.告警或获取用户输入.比如这种: JOptionPane是Swing中的一个对话框类,它能够提供常见的绝大多数对话框效果,本文对这个类进行介绍.需要 ...
- 201521123121 《JAVA程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 201521123005 《Java程序设计》 第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...
- 201521123034《Java程序设计》第十周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...
- 201521123028 《Java程序设计》第12周学习总结
1. 本周学习总结 流与文件 I/O流:Input/Output处理的简称,本质上就是一个数据序列.分为输入流Input Stream和输出流Output Stream. 最基本的可处理数据单位-by ...
- java命令行执行带依赖jar包的main函数
有时候客户端没有运行环境,需要将程序放到服务器上执行,可按如下操作: 1.创建libs文件夹,将运行过程中依赖的jar包全部拷贝到此处; 2.编译.执行 javac -Djava.ext.dirs=l ...
- Jquery基础添加删除内容
直入主题,工作中比较常用的功能在input框内添加内容,不白话了,上代码! 布局: <div id="content"> <input type="te ...