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. 部署自己的GitLab

    先说明一下自己的想法:无论怎么样,个人确实先不想升级到centos7上面,因为我觉得centos6还是比较占用资源少的,而且作为生产环境,centos6完全够用了. 实验测试环境: * centos ...

  2. 201521123061 《Java程序设计》第十一周学习总结

    201521123061 <Java程序设计>第十一周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 本周学习的是如何解决多线程访问中的互斥 ...

  3. 201521123103 《Java学习笔记》 第五次学习总结

    一.本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. (1).接口更灵活.更方便,可以方便的为现有的系统添加新的功能. (2).is-a ...

  4. 201521123068《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 点击查看->高清脑图 1.2 使用常规方法总结其他上课内容. 答:学习继承与多态的知识,了解它们之间的关系:super.ext ...

  5. 201521123104 《JAVA程序设计》第二周学习总结

    1. 本周学习总结 认识了JAVA编程中一些类型与变量,了解了一些基本运算符的使用 变量在命名时,不可以使用数字或一些特殊字符作为开头 不可以声明局部变量后未指定任何值给它之前就使用变量 在程序中写下 ...

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

    0. 本周课程设计发布 Java课程设计 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓 ...

  7. 201521123078 《Java程序设计》第14周学习总结

    1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) 2 ...

  8. 201521123066 《Java程序设计》第九周学习总结

    1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什 ...

  9. python之并发编程之多进程

    一.共享数据 进程间通信应该尽量避免使用本节所讲的共享数据方式 from multiprocessing import Manager,Process,Lock def work(dic,mutex) ...

  10. Babel初体验

    原文地址:→传送门 写在前面 现在es6很流行,尽管各大浏览器都还不能支持它的新特性,但是小伙伴们还是很中意它呀,于是小小的学习的一下 Babel 这里我们不介绍es6相关内容,只是说下入坑前奏,记录 ...