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代码

JHadoop实现了hadoop.fs中的方法调用。

我这里只给出了几个函数的简单封装,你可以根据具体的需要进行增加。

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连接池(Hadoop连接池)的更多相关文章

  1. 对象池化技术 org.apache.commons.pool

    恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率.Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以 ...

  2. 池化 - Apache Commons Pool

    对于那些创建耗时较长,或者资源占用较多的对象,比如网络连接,线程之类的资源,通常使用池化来管理这些对象,从而达到提高性能的目的.比如数据库连接池(c3p0, dbcp), java的线程池 Execu ...

  3. JedisCluster中应用的Apache Commons Pool对象池技术

    对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分.   apache common pool 官方文档可以参考:https://c ...

  4. Apache Commons Pool 故事一则

    Apache Commons Pool 故事一则 最近工作中遇到一个由于对commons-pool的使用不当而引发的问题,习得正确的使用姿势后,写下这个简单的故事,帮助理解Apache Commons ...

  5. apache commons pool

    apache commons下的pool 其中的borrowObject函数源代码显示其产生可用对象的过程: 如果stack中有空闲的对象,则pop对象,激活对象(activate函数),验证对象(v ...

  6. Apache Commons Pool 故事一则 专题

    Apache Commons Pool 故事一则 最近工作中遇到一个由于对commons-pool的使用不当而引发的问题,习得正确的使用姿势后,写下这个简单的故事,帮助理解Apache Commons ...

  7. Tomcat 开发web项目报Illegal access: this web application instance has been stopped already. Could not load [org.apache.commons.pool.impl.CursorableLinkedList$Cursor]. 错误

    开发Java web项目,在tomcat运行后报如下错误: Illegal access: this web application instance has been stopped already ...

  8. NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool

    错误:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool/impl ...

  9. psycopg2.pool – Connections pooling / psycopg2.pool – 连接池 / postgresql 连接池

    创建新的PostgreSQL连接可以是一个昂贵的操作.这个模块提供了一些纯Python类直接在客户端应用程序实现简单的连接池.      class psycopg2.pool.AbstractCon ...

随机推荐

  1. python tornado 实现类禅道系统

    最近楼主加班 喽, 好久没有更新我的博客了,哎,一言难尽,废话我就不说了,来开始上精华. 背景:目前市面上有很多bug管理工具,但是各有各的特点,最著名,最流行的就是禅道,一个偶然的机会接触到了pyt ...

  2. MPLS LDP随堂笔记1

    LDP 的使用原因(对于不同协议来说) LDP的四大功能 发现邻居 hello 5s 15s 224.0.0.2 发现邻居关系 R1 UDP 646端口 R2 UDP 646端口 此时形成邻居 建立邻 ...

  3. EmEditor编辑器正则表达式的优点

    (1)^[ \t]*\n这个正则表达式代表所有的空行,指含有零个或零个以上空格或制表符.以换行符结尾.不含其它字符的行.(2)(^|(?<=中国)).*?(?=中国|$)用正则表达式匹配特定字符 ...

  4. 团队作业8——第二次项目冲刺(Beta阶段) 5.19

    Day1--5.19 1.展开站立式会议(拍摄者:武健男): 会议内容:(1)新成员自我介绍,使大家能更快熟悉并一起合作. (2)由于我们之前的项目经理去了别的小组,所以我们投票选取新成员林乔桦作为我 ...

  5. 201521123088《Java程序设计》第七周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 ArrayList代码分析1.1 解释ArrayList的contains源代码源代码: //contain ...

  6. 201521123117 《Java程序设计》第6周学习总结

    1. 本周学习总结 2. 书面作业 Q1.clone方法 1.Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? 答:在自定义的类中覆盖cl ...

  7. 201521123092,《java程序设计》第1周学习总结

    1.本周学习总结 这一周是我学习java的第一周,刚接触一门全新的编程语言,觉得还是有点困难的,很多基础性的java知识需要一点点学习,我会请教同学以及查询网上的学习资料,认真学好这一门学科. 本周学 ...

  8. mysql:视图,触发器,事务,存储过程,函数

    一.视图 视图是一个虚拟表并不是(正实存在的) 创建老师表 create table teacher( id int primary key auto_increment, tname varchar ...

  9. OSGi-入门篇之模块层(02)

    1 什么是模块化 模块层是OSGi框架中最基础的一部分,其中Java的模块化特性在这一层得到了很好的实现.但是这种实现与Java本身现有的一些模块化特性又有明显的不同. 在OSGi中模块的定义可以参考 ...

  10. 手机管家iPhoneX的适配总结

    WeTest 导读 随着苹果发布会的结束,Xcode的GM版也上线了,也意味着iPhoneX适配之旅的开始. 一.设计关注篇 注意设计的基本原则:(苹果呼吁的) 规格原帖:https://develo ...