文件上传status 400_Spring Boot与Hadoop HDFS分布式文件系统

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

一、HDFS概念

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

2f323630c3756e0340719df315c28e96.png

1.1HDFS适用场景

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

330abc44bc8d3b5e6d43df37fbfad026.png

1.2HDFS缺点

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

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

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

204b8bfae6c54930ed1194778699e8ad.png

1.3HDFS组成部分

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

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

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

1d4dcb4c8521a12d6d91a6d3d63521bd.png

1.4HDFS支持的数据访问格式

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

8dbe817c2d4ce947fee7e67f188dcce2.png

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

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

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

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

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

d0c5e2fa0f00f5c05b35f700bfcffa86.png

三、开启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

e2959bb10aa96268432ba473bb49e3cb.png

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;

}

fdddcd1f84b251818c802cfa677e4101.png

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());

}

}

f8757600b04fa3cc1e9f6ff63cee3693.png

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());

}

}

9c87a11bc0551de5463f1cd7b505538c.png

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;

}

cab831239ad90bd683b198a1380518a6.png

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());

}

}

f7bc31940c89493ecf3289694c260b61.png

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());

}

}

5a5183a36508db7c331ade0ca5447c7f.png

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;

}

e7695630ce3d3bee133fb9bb37cd4425.png

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;

}

80a3cd9c6bfb23fdd36334bf6fc466ec.png

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;

}

}

61e1bf83aaac16d52c1b0799e6ced2e1.png

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;

}

30d16a0be32ce9181f367fe9235f5894.png

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";

}

ae03d3b16ccdef5bc9fe65fcfe1919b0.png

四、Spring Boot后续

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值