Spring Boot与Hadoop HDFS分布式文件系统

一、HDFS概念

HDFS属于Hadoop大数据生态圈,最早是由谷歌GFS论文中引申出来的概念,全名叫做Hadoop Distributed File System。也就是分布式文件系统,按区域进行存储数据。




hadoop和springboot hadoop和springboot有什么区别_hdfs


1.1HDFS适用场景

主要特点是高容错性、大文件存储、高吞吐量。


hadoop和springboot hadoop和springboot有什么区别_文件上传status 400_02


1.2HDFS缺点

由于HDFS是由高数据吞吐量优化的,会造成低时间数据访问延迟;

会造成用户量多任意修改文件;

会造成非常多的小文件,磁盘空间任意消耗。


hadoop和springboot hadoop和springboot有什么区别_hadoop_03


1.3HDFS组成部分

NameNode:是一个元数据,支持存储、生成文件系统;

Client:支持客户端得到数据回传给业务;

DataNode:是HDFS中用于存储实际数据的部分,上报数据给NameNode,支持多个实例。


hadoop和springboot hadoop和springboot有什么区别_hadoop和springboot_04


1.4HDFS支持的数据访问格式

可支持WebHDFS和HTTPFS,本文将以Spring Boot操作HTTPFS来说明Spring Boot操作HDFS形式。


hadoop和springboot hadoop和springboot有什么区别_hadoop_05


二、HDFS 支持Java API主要工具类

[A]用于获取服务器和客户端配置信息的Configuration;

[B]用于生成获取文件系统的FileSystem;

[C]HDFS中的数据输入流,用于FileSystem的open方法的FSDataInputStream;

[D]HDFS的数据输出流,由FileSystem Create方法生成的FSDataOutputStream。


hadoop和springboot hadoop和springboot有什么区别_hadoop和springboot_06


三、开启Spring Boot项目支持HDFS

首先引入Spring Boot工程的父模块依赖,组成Spring Boot工程:

org.springframework.boot
 spring-boot-starter-parent
 2.1.6.RELEASE
引入Spring Boot组件:
 org.springframework.boot
 spring-boot-starter
 org.springframework.boot
 spring-boot-starter-web
引入Hadoop工具包:
 org.apache.hadoop
 hadoop-common
 3.1.1
引入Hadoop HDFS支撑组件:
 org.apache.hadoop
 hadoop-hdfs
 3.1.1
引入Hadoop客户端工具:
 org.apache.hadoop
 hadoop-client
 3.1.1
引入MR支持组件:
 org.apache.hadoop
 hadoop-mapreduce-client-core
 3.1.1
构建Maven工程:
 org.springframework.boot
 spring-boot-maven-plugin
 org.apache.maven.plugins
 maven-compiler-plugin
 1.8
 1.8
主要启动文件bootstrap.yml配置:
hadoop.name-node: hdfs://192.168.1.82:9000
hadoop.namespace: /myora
# hadoop:
# fs-uri: hdfs://192.168.1.82:9000


hadoop和springboot hadoop和springboot有什么区别_文件上传status 400_07


3.1编写HDFS工具类

3.1.1获取文件系统

public class HdfsHutools {
 /**
 * 获取文件系统
 * @return
 */
 public static FileSystem getFileSystem(String hdfsClientUri) {
 //读取配置文件
 Configuration conf = new Configuration();
 // 文件系统
 FileSystem fs = null;
 if(StringUtils.isBlank(hdfsClientUri)){
 // 返回默认文件系统 如果在 Hadoop集群下运行,使用此种方法可直接获取默认文件系统
 try {
 fs = FileSystem.get(conf);
 } catch (Exception e) {
 System.out.print("异常"+ e.toString());
 }
 }else{
 // 返回指定的文件系统,如果在本地测试,需要使用此种方法获取文件系统
 try {
 URI uri = new URI(hdfsClientUri.trim());
 fs = FileSystem.get(uri,conf);
 } catch (Exception e) {
 System.out.print("异常"+ e.toString());
 }
 }
 return fs;
 }


hadoop和springboot hadoop和springboot有什么区别_hdfs_08


3.1.2创建HDFS文件目录

public static void mkdir(String hdfsCreateUri, String path) {
 try {
 // 获取HDFS文件系统
 FileSystem fs = getFileSystem(hdfsCreateUri);
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 path = hdfsCreateUri+ path;
 }
 // 创建目录
 fs.mkdirs(new Path(path));
 //释放资源
 fs.close();
 } catch (Exception e) {
 System.out.print("异常"+ e.toString());
 }
 }


hadoop和springboot hadoop和springboot有什么区别_hadoop和springboot_09


3.1.3删除HDFS文件目录

public static void rmdir(String hdfsCreateUri,String path) {
 try {
 // 返回FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 path = hdfsCreateUri+ path;
 }
 // 删除文件或者文件目录 delete(Path f) 此方法已经弃用
 fs.delete(new Path(path),true);
 // 释放资源
 fs.close();
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 }

3.1.4过滤掉HDFS目录下的文件

public static String[] listFile(String hdfsCreateUri, String path,PathFilter pathFilter) {
 String[] files = new String[0];
 try {
 // 返回FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 path = hdfsCreateUri+ path;
 }
 FileStatus[] status;
 if(pathFilter != null){
 // 根据filter列出目录内容
 status = fs.listStatus(new Path(path),pathFilter);
 }else{
 // 列出目录内容
 status = fs.listStatus(new Path(path));
 }
 // 获取目录下的所有文件路径
 Path[] listedPaths = FileUtil.stat2Paths(status);
 // 转换String[]
 if (listedPaths != null && listedPaths.length > 0){
 files = new String[listedPaths.length];
 for (int i = 0; i < files.length; i++){
 files[i] = listedPaths[i].toString();
 }
 }
 // 释放资源
 fs.close();
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 return files;
 }


hadoop和springboot hadoop和springboot有什么区别_hadoop_10


3.1.5上传文件至HDFS

public static void copyFileToHDFS(String hdfsCreateUri,boolean delSrc, boolean overwrite,String srcFile,String destPath) {
 Path srcPath = new Path(srcFile);
 // 目的路径
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 destPath = hdfsCreateUri+ destPath;
 }
 Path dstPath = new Path(destPath);
 // 实现文件上传
 try {
 // 获取FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 fs.copyFromLocalFile(srcPath, dstPath);
 fs.copyFromLocalFile(delSrc,overwrite,srcPath, dstPath);
 //释放资源
 fs.close();
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 }


hadoop和springboot hadoop和springboot有什么区别_hadoop_11


3.1.6从HDFS下载文件

public static void getFile(String hdfsCreateUri, String srcFile,String destPath) {
 // 源文件路径
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 srcFile = hdfsCreateUri+ srcFile;
 }
 Path srcPath = new Path(srcFile);
 Path dstPath = new Path(destPath);
 try {
 // 获取FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 // 下载hdfs上的文件
 fs.copyToLocalFile(srcPath, dstPath);
 // 释放资源
 fs.close();
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 }


hadoop和springboot hadoop和springboot有什么区别_文件上传status 400_12


3.1.7获取HDFS集群节点信息

public static DatanodeInfo[] getHDFSNodes(String hdfsCreateUri) {
 // 获取所有节点
 DatanodeInfo[] dataNodeStats = new DatanodeInfo[0];
 try {
 // 返回FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 // 获取分布式文件系统
 DistributedFileSystem hdfs = (DistributedFileSystem)fs;
 dataNodeStats = hdfs.getDataNodeStats();
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 return dataNodeStats;
 }


hadoop和springboot hadoop和springboot有什么区别_文件上传status 400_13


3.1.8获取文件位置

public static BlockLocation[] getFileBlockLocations(String hdfsCreateUri, String filePath) {
 // 文件路径
 if(StringUtils.isNotBlank(hdfsCreateUri)){
 filePath = hdfsCreateUri+ filePath;
 }
 Path path = new Path(filePath);
 // 文件块位置列表
 BlockLocation[] blkLocations = new BlockLocation[0];
 try {
 // 返回FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 // 获取文件目录
 FileStatus filestatus = fs.getFileStatus(path);
 //获取文件块位置列表
 blkLocations = fs.getFileBlockLocations(filestatus, 0, filestatus.getLen());
 } catch (Exception e) {
System.out.print("异常"+ e.toString());
 }
 return blkLocations;
 }

hadoop和springboot hadoop和springboot有什么区别_hadoop和springboot_14


3.1.9判断HDFS目录是否存在

public boolean existDir(String hdfsCreateUri,String filePath, boolean create){
 boolean flag = false;
 if (StringUtils.isEmpty(filePath)){
 return flag;
 }
 try{
 Path path = new Path(filePath);
 // FileSystem对象
 FileSystem fs = getFileSystem(hdfsCreateUri);
 if (create){
 if (!fs.exists(path)){
 fs.mkdirs(path);
 }
 }
 if (fs.isDirectory(path)){
 flag = true;
 }
 }catch (Exception e){
System.out.print("异常"+ e.toString());
 }
 return flag;
 }
}


hadoop和springboot hadoop和springboot有什么区别_hadoop_15


3.2HDFS的Spring Boot配置

@Configuration
@ConditionalOnProperty(name="hadoop.name-node")
@Slf4j
public class HDFSClientConfig {
@Value("${hadoop.name-node}")
 private String nameNode;
@Bean("fileSystem")
 public FileSystem createHDFSFile() {
 //读取HDFS Config
 Configuration conf = new Configuration();
 conf.set("fs.defalutFS", nameNode);
 conf.set("dfs.replication", "1");
 FileSystem fs = null;
 //conf.set("fs.defaultFS","hdfs://ns1");
 //指定访问HDFS的client信息
 //fs = FileSystem.get(new URI(nameNode), conf, "root");
 // 文件HDFS系统
 try {
 URI uri = new URI(nameNode.trim());
 fs = FileSystem.get(uri,conf,"root");
 } catch (Exception e) {
 System.out.println(e.toString());
 }
 System.out.println("fs.defaultFS: "+conf.get("fs.defaultFS"));
 return fs;
 }


hadoop和springboot hadoop和springboot有什么区别_hdfs_16


3.3Restful格式Controller代码示例

删除HDFS文件:

@GetMapping("/delete")
 public String delete(@RequestParam String fileName){
 hadoopUtil.rmdir(fileName,"");
 return "delete";
 }
下载HDFS文件:
@GetMapping("/downloadToDest")
 public String downloadToDest(@RequestParam String fileName,@RequestParam String savePath){
 hadoopUtil.getFile(fileName,"",savePath);
 return "downloadToDest";
 }


hadoop和springboot hadoop和springboot有什么区别_hadoop和springboot_17


四、Spring Boot后续

Spring Boot本人水平也有限,如有不对,还望指正。