HDFS,全称Hadoop分布式文件系统,作为Hadoop生态技术圈底层的关键技术之一,被设计成适合运行在通用硬件上的分布式文件系统。它和现有的分布式文件系统有很多共同点,但同时,它和其他的分布式文件系统的区别也是很明显的。HDFS是一个高度容错性的系统,适合部署在连接的机器上。HDFS能够提供高吞吐量的数据访问,非常适合大规模数据集上的应用。
笔者本人接触研究HDFS也有半年之久了,了解了HDFS Java API接口后,就一直设想着设计一个类似于Windows操作系统上的资源管理器一样的小工具,用来管理分布式文件资源。其实,Hadoop Web UI和HUE都自带有WEB版本的分布式文件浏览器,但是在文件信息管理方面不够讨人喜欢,可能笔者本人习惯了Windows上的资源管理器那样的操作习惯。于是利用闲暇时间,经过几个月断断续续的设计完善,最终开发出了一个类似Windows资源管理器一样的管理工具,暂且就叫做“HDFS分布式文件资源管理器”,现在把设计思路过程总结一下,贴在网络上,希望能够对感兴趣的朋友们有所帮助。成型后的资源管理器界面如下图所示:
朋友们可以看出来,笔者本人是采用Eclipse+Swing方式进行开发设计的,界面上没有动用第三方的UI组件,所以看起来稍显朴素,不过这都不是重点,关键是它在Windows和Linux下都运行良好,为笔者进行分布式文件管理提供了大大的便利。
1. 开发过程概述
笔者先大致讲述下此工具的开发过程。
第一步是封装了一下HDFS Java API接口。对组件系统提供的API接口方法进行二次封装好像已经成为了笔者本人的习惯了,如果不能按照自己的软件开发习惯调用接口方法,就总是感觉怪怪的。
第二步是功能模块设计。功能模块梳理比较轻松,一是因为自己的需求比较明确,二是因为有Windows资源管理器可以做参考。梳理后的主要功能包括几点:
目录导航树。类似Window资源管理器左侧的目录导航树。
目录文件列表。以JTable列表展示目录文件信息,类似于Windows资源管理器的List视图。
创建、重命名和删除目录。
重命名和删除文件。
上传文件(没有提供新建文件的功能)。
下载文件。
移动目录文件。
查看目录文件属性。
目录文件权限配置。
2. HDFS Java API二次封装
对HDFS Java API进行二次封装,并不仅仅是为了设计开发HDFS分布式文件系统资源管理器,还要尽量考虑日后针对HDFS的其他后续开发,所以在封装的时候,尽量让自己目光看的远一些。
封装编译后的jar文件命名为hnepri-hadoop-common.jar,里面也包含有针对HBase Java API的二次封装接口方法,所以命名为hadoop-common包,特此说明下。下图是开发工程结构图:
主要包括两个工具类文件:HadoopConfigUtil和HadoopFileUtil。其中,HadoopConfigUtil为HDFS配置管理类,负责与Hadoop建立连接和信息配置;HadoopFileUtil为HDFS文件目录操作工具类。
2.1. HadoopConfigUtil
HDFS的核心配置文件是core-site.xml和hdfs-site.xml,构建Configuration对象时读取这两个配置文件即可,如果有其他的自定义配置信息,可以将其配置在hadoop.config.properties文件。
另外需要特别强调的是,在Windows下利用API接口方法操作HDFS时会遇到权限认证的问题,类似“Permission denied: user=XXXXX,access=WRITE,inode=......”等一样的错误。这主要是由于当前用户与HDFS默认用户不一致所造成的,针对这种情况,有三种解决方案:
第一、在hdfs配置文件中,将dfs.permissions修改为false,即取消HDFS的安全权限认证机制。
第二、在hdfs文件系统中为指定目录赋予当前用户操作的权限,譬如执行hadoop fs -chmod 777 /user/hadoop等。
第三、在环境变量中创建HADOOP_USER_NAME选项,其值为HDFS对应的用户名称,譬如hadoop或者hdfs,然后重新启动计算机和Eclipse以使环境变量生效。
针对开发人员而言,我们推荐第三种解决方案。配置方法参考下图:
以下为HadoopConfigUtil类详细信息。
import java.io.File;
import java.util.HashMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import com.hnepri.common.util.PropertiesUtil;
/**
* Description: Hadoop信息配置工具类<br>
* Copyright: Copyright (c) 2015<br>
* Company: 河南电力科学研究院智能电网所<br>
* @author shangbingbing 2015-01-01编写
* @version 1.0
*/
public class HadoopConfigUtil {
/**
* 加载解析Hadoop自定义配置信息。<br>
* 需在系统启动时调用此方法加载自定义配置信息,否则将采用默认配置或者无法连接Hadoop。
*/
public static void loadHadoopConfigProperties() {
String path = "hadoop.config.properties";
HashMap<String,String> pps = PropertiesUtil.readProperties(path);
HadoopConfigUtil.setHadoopConfigItemList(pps);
}
private static Configuration conf = null;
/**
* hadoop配置信息列表,其中key中存储参数名称,譬如master.hadoop;value中存储参数值,譬如master.hadoop:9000等
*/
private static HashMap<String,String> hadoopConfigItemList = new HashMap<String,String>();
/**
* 获取hadoop配置信息列表
* @return
*/
public static HashMap<String, String> getHadoopConfigItemList() {
return hadoopConfigItemList;
}
/**
* 设置hadoop配置信息列表
* @param hadoopConfigItemList
*/
public static void setHadoopConfigItemList(HashMap<String, String> hadoopConfigItemList) {
HadoopConfigUtil.hadoopConfigItemList = hadoopConfigItemList;
}
/**
* 添加hadoop配置信息
* @param key
* @param value
*/
public static void addHadoopConfigItem(String key,String value) {
if(hadoopConfigItemList.containsKey(key)) {
hadoopConfigItemList.remove(key);
}
hadoopConfigItemList.put(key, value);
}
/**
* 删除hadoop配置信息
* @param key
*/
public static void removeHadoopConfigItem(String key) {
if(hadoopConfigItemList.containsKey(key)) {
hadoopConfigItemList.remove(key);
}
}
/**
* 获取Hadoop Configuration对象
* @return
*/
public static Configuration getHadoopConfig() {
if(conf == null) {
conf = new Configuration();
try {
//解决winutils.exe不存在的问题
File workaround = new File(".");
System.getProperties().put("hadoop.home.dir", workaround.getAbsolutePath());
new File("./bin").mkdirs();
new File("./bin/winutils.exe").createNewFile();
conf.addResource("core-site.xml");
conf.addResource("hdfs-site.xml");
//初始化设置zookeeper相关配置信息
if(hadoopConfigItemList != null && hadoopConfigItemList.size() > 0) {
for(String key : hadoopConfigItemList.keySet()) {
String value = hadoopConfigItemList.get(key);
conf.set(key, value);
}
}
}
catch (Exception ex) {
System.out.println(ex.toString());
}
}
return conf;
}
/**
* 刷新重置Hadoop配置对象
*/
public static void initHadoopConfig() {
conf = null;
}
private static FileSystem fileSystem = null;
/**
* 获取FileSystem文件系统对象
* @return
*/
public static FileSystem getFileSystem() {
if(fileSystem == null) {
try {
fileSystem = FileSystem.get(getHadoopConfig());
} catch (Exception e) {
e.printStackTrace();
}
}
return fileSystem;
}
/**
* 获取HDFS文件系统对象
* @return
*/
public static DistributedFileSystem getHDFS() {
return (DistributedFileSystem)getFileSystem();
}
}
2.2. HadoopFileUtil