Java hdfs连接池_Java使用连接池管理Hdfs连接

记录一下Java API 连接hadoop操作hdfs的实现流程(使用连接池管理)。

以前做过这方面的开发,本来以为不会有什么问题,但是做的还是坑坑巴巴,内心有些懊恼,记录下这烦人的过程,警示自己切莫眼高手低!

一:引入相关jar包如下

org.apache.hadoop

hadoop-common

2.8.2

org.apache.hadoop

hadoop-hdfs

2.8.2

org.apache.commons

commons-pool2

2.6.0

二:连接池开发的基本流程

2.1项目基本环境是SpringBoot大集成···

2.2hadoop相关包结构如下(自己感觉这结构划分的也是凸显了low逼水平【手动笑哭】)

9051ef3df767bb1eb8511b67db1d5ad3.png

2.2 画个图表达下开发思路

761d38a3bfb5588c62b9780d6db8c3af.png

三、上代码

importcom.cmcc.datacenter.hdfs.client.HdfsClient;importcom.cmcc.datacenter.hdfs.client.HdfsFactory;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;

@Configurationpublic classHdfsConfig {

@Value("${hadoop.hdfs.ip}")privateString hdfsServerIp;

@Value("${hadoop.hdfs.port}")privateString hdfsServerPort;

@Value("${hadoop.hdfs.pool.maxTotal}")private intmaxTotal;

@Value("${hadoop.hdfs.pool.maxIdle}")private intmaxIdle;

@Value("${hadoop.hdfs.pool.minIdle}")private intminIdle;

@Value("${hadoop.hdfs.pool.maxWaitMillis}")private intmaxWaitMillis;

@Value("${hadoop.hdfs.pool.testWhileIdle}")private booleantestWhileIdle;

@Value("${hadoop.hdfs.pool.minEvictableIdleTimeMillis}")private long minEvictableIdleTimeMillis = 60000;

@Value("${hadoop.hdfs.pool.timeBetweenEvictionRunsMillis}")private long timeBetweenEvictionRunsMillis = 30000;

@Value("${hadoop.hdfs.pool.numTestsPerEvictionRun}")private int numTestsPerEvictionRun = -1;

@Bean(initMethod= "init", destroyMethod = "stop")publicHdfsClient HdfsClient(){

HdfsClient client= newHdfsClient();returnclient;

}/*** TestWhileConfig - 在空闲时检查有效性, 默认false

* MinEvictableIdleTimeMillis - 逐出连接的最小空闲时间

* TimeBetweenEvictionRunsMillis - 逐出扫描的时间间隔(毫秒) 如果为负数则不运行逐出线程,默认-1

* NumTestsPerEvictionRun - 每次逐出检查时 逐出的最大数目

**/@BeanpublicHdfsPoolConfig HdfsPoolConfig(){

HdfsPoolConfig hdfsPoolConfig= newHdfsPoolConfig();

hdfsPoolConfig.setTestWhileIdle(testWhileIdle);

hdfsPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

hdfsPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

hdfsPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);

hdfsPoolConfig.setMaxTotal(maxTotal);

hdfsPoolConfig.setMaxIdle(maxIdle);

hdfsPoolConfig.setMinIdle(minIdle);

hdfsPoolConfig.setMaxWaitMillis(maxWaitMillis);returnhdfsPoolConfig;

}

@BeanpublicHdfsFactory HdfsFactory(){return new HdfsFactory("hdfs://" + hdfsServerIp + ":" +hdfsServerPort);

}

}

importorg.apache.commons.pool2.impl.GenericObjectPoolConfig;public class HdfsPoolConfig extendsGenericObjectPoolConfig {publicHdfsPoolConfig(){}/*** TestWhileConfig - 在空闲时检查有效性, 默认false

* MinEvictableIdleTimeMillis - 逐出连接的最小空闲时间

* TimeBetweenEvictionRunsMillis - 逐出扫描的时间间隔(毫秒) 如果为负数则不运行逐出线程,默认-1

* NumTestsPerEvictionRun - 每次逐出检查时 逐出的最大数目

**/

public HdfsPoolConfig(boolean testWhileIdle, long minEvictableIdleTimeMillis, long timeBetweenEvictionRunsMillis, intnumTestsPerEvictionRun){this.setTestWhileIdle(testWhileIdle);this.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);this.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);this.setNumTestsPerEvictionRun(numTestsPerEvictionRun);

}

}

packagecom.cmcc.datacenter.hdfs.client;importcom.cmcc.datacenter.hdfs.config.HdfsPoolConfig;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importjava.util.List;public classHdfsClient {private Logger logger = LoggerFactory.getLogger(this.getClass());privateHdfsPool hdfsPool;

@AutowiredprivateHdfsPoolConfig hdfsPoolConfig;

@AutowiredprivateHdfsFactory hdfsFactory;public voidinit(){

hdfsPool= newHdfsPool(hdfsFactory,hdfsPoolConfig);

}public voidstop(){

hdfsPool.close();

}public long getPathSize(String path) throwsException {

Hdfs hdfs= null;try{

hdfs=hdfsPool.borrowObject();returnhdfs.getContentSummary(path).getLength();

}catch(Exception e) {

logger.error("[HDFS]获取路径大小失败", e);throwe;

}finally{if (null !=hdfs) {

hdfsPool.returnObject(hdfs);

}

}

}public ListgetBasePath(){

Hdfs hdfs= null;try{

hdfs=hdfsPool.borrowObject();returnhdfs.listFileName();

}catch(Exception e) {

e.printStackTrace();return null;

}finally{if (null !=hdfs) {

hdfsPool.returnObject(hdfs);

}

}

}

}

importorg.apache.commons.pool2.PooledObject;importorg.apache.commons.pool2.PooledObjectFactory;importorg.apache.commons.pool2.impl.DefaultPooledObject;importjava.io.IOException;public class HdfsFactory implements PooledObjectFactory{private finalString url;publicHdfsFactory(String url){this.url =url;

}

@Overridepublic PooledObject makeObject() throwsException {

Hdfs hdfs= newHdfs(url);

hdfs.open();return new DefaultPooledObject(hdfs);

}

@Overridepublic void destroyObject(PooledObject pooledObject) throwsException {

Hdfs hdfs=pooledObject.getObject();

hdfs.close();

}

@Overridepublic boolean validateObject(PooledObjectpooledObject) {

Hdfs hdfs=pooledObject.getObject();try{returnhdfs.isConnected();

}catch(IOException e) {

e.printStackTrace();return false;

}

}

@Overridepublic void activateObject(PooledObject pooledObject) throwsException {

}

@Overridepublic void passivateObject(PooledObject pooledObject) throwsException {

}

}

packagecom.cmcc.datacenter.hdfs.client;importorg.apache.commons.pool2.PooledObjectFactory;importorg.apache.commons.pool2.impl.AbandonedConfig;importorg.apache.commons.pool2.impl.GenericObjectPool;importorg.apache.commons.pool2.impl.GenericObjectPoolConfig;public class HdfsPool extends GenericObjectPool{public HdfsPool(PooledObjectFactoryfactory) {super(factory);

}public HdfsPool(PooledObjectFactory factory, GenericObjectPoolConfigconfig) {super(factory, config);

}public HdfsPool(PooledObjectFactory factory, GenericObjectPoolConfigconfig, AbandonedConfig abandonedConfig) {super(factory, config, abandonedConfig);

}

}

importcom.cmcc.datacenter.hdfs.config.HdfsConfig;importcom.google.common.collect.Lists;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.ContentSummary;importorg.apache.hadoop.fs.FileStatus;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Autowired;importjava.io.IOException;importjava.util.List;public classHdfs {private Logger logger = LoggerFactory.getLogger(this.getClass());privateFileSystem fs;privateString coreResource;privateString hdfsResource;private finalString url;private static final String NAME = "fs.hdfs.impl";publicHdfs(String url) {this.url =url;

}public voidopen() {try{

Configuration conf= newConfiguration();

conf.set("fs.defaultFS", url);

System.out.println("url is "+url);

fs=FileSystem.get(conf);

logger.info("[Hadoop]创建实例成功");

}catch(Exception e) {

logger.error("[Hadoop]创建实例失败", e);

}

}public voidclose() {try{if (null !=fs) {

fs.close();

logger.info("[Hadoop]关闭实例成功");

}

}catch(Exception e) {

logger.error("[Hadoop]关闭实例失败", e);

}

}public boolean isConnected() throwsIOException {return fs.exists(new Path("/"));

}public boolean exists(String path) throwsIOException {

Path hdfsPath= newPath(path);returnfs.exists(hdfsPath);

}public FileStatus getFileStatus(String path) throwsIOException {

Path hdfsPath= newPath(path);returnfs.getFileStatus(hdfsPath);

}public ContentSummary getContentSummary(String path) throwsIOException {

ContentSummary contentSummary= null;

Path hdfsPath= newPath(path);if(fs.exists(hdfsPath)) {

contentSummary=fs.getContentSummary(hdfsPath);

}returncontentSummary;

}public List listFileName() throwsIOException {

List res =Lists.newArrayList();

FileStatus[] fileStatuses= fs.listStatus(new Path("/"));for(FileStatus fileStatus : fileStatuses){

res.add(fileStatus.getPath()+":类型--"+ (fileStatus.isDirectory()? "文件夹":"文件"));

}returnres;

}

}

四、总结:

一共六个类,理清思路看是很easy的。

这里就是spring对类的管理和commons-pool2对连接类的管理混着用了,所以显得有点乱。

1.@Configuration注解加到Hdfsconfig类上,作为一个配置类,作用类似于spring-xml文件中的标签,springboot会扫描并注入它名下管理的类,其中

@Bean(initMethod = "init", destroyMethod = "stop") 标签表示spring在初始化这个类时调用他的init方法,销毁时调用他的stop方法。

2.HdfsClient 是业务方法调用的类,spring在初始化这个类时,调用它的init方法,这个方法会创建HdfsPool(即Hdfs的连接池)。其他方法是对Hdfs中方法的二次封装,即先使用连接池获取实例,再调用实例方法。

3.HdfsPoolConfig继承commons-pool2包中的GenericObjectConfig,受spring管理,作为线程池的配置类,创建HdfsPool时作为参数传入。

4.HdfsFactory继承commons-pool2包中的GenericObjectFactory,受spring管理,作为创建连接实例的工厂类,创建HdfsPool时作为参数传入。实际上连接池就是通过它获取的连接实例。

5.HdfsPool继承commons-pool2包中的GenericObjectPool,是连接池。

6.Hdfs,是底层的连接实例,所有增删改查的方法都要在这里实现,只不过获取/销毁连接交给池管理。

声明:这里用spring管理一些类是应为项目本身用的springboot,spring管理方便,并不是强制使用,愿意完全可以自己new。

五、不得不说的一些不是坑的坑。

1.我真的不记得windows上用Java API连接远程的hadoop还要有一些神操作。

报错如下:java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir are unset

解决如下:

1. 将已下载的 hadoop-2.9.0.tar 这个压缩文件解压,放到你想要的位置(本机任意位置);

2. 下载 windows 环境下所需的其他文件(hadoop2.9.0对应的hadoop.dll,winutils.exe 等),这步真是关键,吐槽某SDN想钱想疯了啊,霸占百度前10页,各种下载各种C币,各种要钱。

不多说了,附上github地址:github地址

3. 拿到上面下载的windows所需文件,执行以下步骤:

3.1:将文件解压到你解压的 hadoop-2.9.0.tar 的bin目录下(没有的放进去,有的不要替换,以免花式作死,想学习尝试的除外)

3.2:将hadoop.dll复制到C:\Window\System32下

3.3:添加环境变量HADOOP_HOME,指向hadoop目录

3.4:将%HADOOP_HOME%\bin加入到path里面,不管用的话将%HADOOP_HOME%\sbin也加进去。

3.5:重启 IDE(你的编辑工具,例如eclipse,intellij idea)

原文:https://www.cnblogs.com/peripateticism/p/10895903.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为了拿捏 Redis 数据结构,我画了 40 张图(完整版)

Redis 为什么那么快? 除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效的处理。 因此,这次我们就来…

fastjson为什么默认是无序的

在做项目的时候,无意间发现添加到json中的元素是无存放顺序的。严格来说,json默认是有存放顺序的,不过是采用HashCode值来排序。下面来看一段源码 上图展示了创建json对象的一个过程,可以清晰的看出,无论用户调用哪个…

Java之HashMap.values()转List时的错误和正确操作

因为项目中需要获取到Map的值的集合&#xff0c;所以调用了HashMap.values()方法转成List&#xff0c;当时是使用了以下代码。&#xff08;逻辑上这样想应该没问题&#xff0c;但生活总是会是不是给你一点小“”惊喜“”&#xff09; List<AreaItemOpt> areaItemOpts (…

php检测表大小,查询mysql数据库、表的大小

一、关于mysql表数据大小mysql存储数据文件一般使用表空间存储 &#xff1b;当mysql使用innodb存储引擎的时候&#xff0c;mysql使用表存储数据分为共享表空间和独享表空间两种方式 。共享表空间&#xff1a;Innodb的所有数据保存在一个单独的表空间里面&#xff0c;而这个表空…

springboot使用redis(StringRedisTemplate的常用方法)

1. 先了解RedisTemplate和StringRedisTemplate之间的关系&#xff1a; RedisTemplate是Spring对于Redis的封装&#xff0c;而StringRedisTemplate继承RedisTemplate。两者的数据是不共通的&#xff1b;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据&…

Arrays.asList()和Collections.singletonList()比较

Collections.singletonList(something)是不可变的&#xff0c; 对Collections.singletonList(something)返回的列表所做的任何更改将导致UnsupportedOperationException。 Arrays.asList(something)允许Arrays.asList(something) 更改 。 此外&#xff0c;由Collections.sin…

php 邮件类库,[3.3]-扩展类库:基于PHPMailer的邮件发送 | PhalApi(π框架) - PHP轻量级开源接口框架 - 接口,从简单开始!...

3.3.1 扩展类库&#xff1a;基于PHPMailer的邮件发送此扩展可用于发送邮件。3.3.2 安装和配置从 PhalApi-Library 扩展库中下载获取 PHPMailer 包&#xff0c;如使用&#xff1a;$ git clone https://git.oschina.net/dogstar/PhalApi-Library.git然后把 PHPMailer 目录复制到 …

spring boot报FileSizeLimitExceededException异常的解决方法

开发spring boot程序时&#xff0c;遇到了如下错误&#xff1a; The field file exceeds its maximum permitted size of 1048576 bytes. 原因&#xff1a; Spring Boot工程嵌入的tomcat限制了请求的文件大小&#xff0c;官方文档中这样描述&#xff1a; Spring Boot embraces…

前后端分离中的权限管理思路

在传统的前后端不分的开发中&#xff0c;权限管理主要通过过滤器或者拦截器来进行&#xff08;权限管理框架本身也是通过过滤器来实现功能&#xff09;&#xff0c;如果用户不具备某一个角色或者某一个权限&#xff0c;则无法访问某一个页面。 但是在前后端分离中&#xff0c;…

前、后端分离权限控制设计与实现

简述 近几年随着react、angular、vue等前端框架兴起&#xff0c;前后端分离的架构迅速流行。但同时权限控制也带来了问题。 网上很多前、后端分离权限仅仅都仅仅在描述前端权限控制、且是较简单、固定的角色场景&#xff0c;满足不了我们用户、角色都是动态的场景。且仅仅前端…

前后端分离必备的接口规范,十分接地气

1. 前言 随着互联网的高速发展&#xff0c;前端页面的展示、交互体验越来越灵活、炫丽&#xff0c;响应体验也要求越来越高&#xff0c;后端服务的高并发、高可用、高性能、高扩展等特性的要求也愈加苛刻&#xff0c;从而导致前后端研发各自专注于自己擅长的领域深耕细作。 然…

ubuntu php设置,关于ubuntu php环境设置详解-PHP问题

ubuntu php设置办法&#xff1a;起首更新源列表&#xff1b;而后关上“终端窗口”&#xff0c;输出饬令“sudo apt-get install php5”来装置php&#xff1b;接着装置设置装备摆设好apache环境&#xff0c;并装置php5-gd模块&#xff1b;最初创立“info.php”文件便可。Ubuntu …

MyBatis-Plus——增删查改

开发环境 IDEA JDK&#xff1a;1.8 Spring Boot:2.6.2 Maven:3.3.9 MySQL:8.0.23 数据库准备 CREATE DATABASE mybatis_plus_db;DROP TABLE IF EXISTS person; CREATE TABLE person(id BIGINT(20) NOT NULL COMMENT 主键ID, name VARCHAR(30) NULL DEFAULT NULL COMMENT 姓…

让程序员最爽的ThreadLocal使用姿势

一、常见场景 ​ 1、ThreadLocal作为线程上下文副本&#xff0c;那么一种最常见的使用方式就是用来方法隐式传参&#xff0c;通过提供的set()和get()两个public方法来实现在不同的方法中的参数传递。对于编程规范来说&#xff0c;方法定义的时候是对参数个数是有限制的&#x…

一场事故告诉你zookeeper和nacos谁更适合做注册中心

前言 ​ 在分布式系统中&#xff0c;注册中心充当着重要角色&#xff0c;是服务发现、客户端负载均衡中不可缺少的一员。注册中心除了能够实现基本的功能外&#xff0c;他的稳定性、可用性和健壮性对整个分布式系统的流畅运行影响重大。dubbo作为国内一款主流的分布式系统&…

Mysql执行计划含义,mysql执行计划介绍

烂sql不仅直接影响sql的响应时间&#xff0c;更影响db的性能&#xff0c;导致其它正常的sql响应时间变长。如何写好sql&#xff0c;学会看执行计划至关重要。下面我简单讲讲mysql的执行计划&#xff0c;只列出了一些常见的情况&#xff0c;希望对大家有所帮助。测试表结构&…

寄生虫php版,-PHP版SEO最新教材版排名DeDeCms寄生虫V90繁殖

今天视频教程演示说明下PHP寄生虫服务端的使用。主要在很多搭建的过程中会出错&#xff0c;今天主要就讲解下寄生虫配置常见的问题。那么同样也可以看下我们之前的通用版寄生虫使用教程[通用版教程在文件夹中有]&#xff0c;本教程是针对PHP版本的寄生虫服务端进行配置演示。继…

MySQL中 JSON 数据类型应用

前言 今天接触到mysql中json数据类型&#xff0c;之前不知道有这个类型&#xff0c;今天学习一下。 JSON我相信大家都已经很熟悉了&#xff0c;但在 MySQL中&#xff0c;直至 5.7 版本中&#xff0c;才正式引入 JSON数据类型。在次之前&#xff0c;我们通常使varchar或text数…

MySql中json类型的使用___mybatis存取mysql中的json

MySql中json类型的使用 MySQL从5.7.8起开始支持JSON字段&#xff0c;这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能&#xff0c;至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能…

百度下拉词+php,百度下拉词是如何生成的?

我们在百度搜索某一词汇的时候&#xff0c;都会在搜索框下面弹出一些相关性和搜索次数比较多的语句或词语&#xff0c;我们在百度上搜索一下&#xff0c;就可以看到用户平时搜索习惯&#xff0c;搜索爱好是什么。护发下拉很多小伙伴就又有疑问了&#xff1a;这些下拉词是根据什…