1.HDFS API 示例
1.1 Client API
1)筹备工作
自己习惯应用 Ubuntu,ide 工具则是 idea,如果是 windows 零碎或者 eclipse 自行百度吧,我没有试过。
老套路,创立 Maven 工程,导入依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client-api</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client-runtime</artifactId>
<version>3.1.3</version>
</dependency>
在 resources 下增加日志配置文件“log4j2.xml”
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" strict="true" name="XMLConfig">
<Appenders>
<Appender type="Console" name="STDOUT">
<Layout type="PatternLayout"
pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c{10}]%m%n" />
</Appender>
</Appenders>
<Loggers>
<Logger name="test" level="info" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
<Root level="info">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
2)在 src/main/java 下创立包 cn.leaf。能够随便,之后创立类 HdfsClient,客户端的应用大抵如下
public void hdClient() throws IOException, InterruptedException {
// 取得一个客户端对象
URI uri = URI.create("hdfs://hadoop10:9820");
Configuration conf = new Configuration();
String user = "v2admin";
FileSystem fs = FileSystem.get(uri,conf,user);
// TODO 执行操作
// 敞开资源
fs.close();}
1.2 上传文件示例代码
public static void main(String[] args) throws IOException, InterruptedException {
// 取得一个客户端对象
URI uri = URI.create("hdfs://hadoop10:9820");
Configuration conf = new Configuration();
String user = "v2admin";
FileSystem fs = FileSystem.get(uri,conf,user);
// TODO 执行操作
Path upsrc = new Path("/home/zhaow/ 桌面 /Shell/passwd.txt");
Path updst = new Path("/home");
upFile(fs,upsrc,updst);
// 敞开资源
fs.close();}
/**
* 上传文件
* @param fs Client 对象
* @param src 待上传文件
* @param dst hdfs 门路
*/
public static void upFile(FileSystem fs, Path src, Path dst){
try {fs.copyFromLocalFile(src, dst);
} catch (IOException e) {e.printStackTrace();
}
}
1.3 下载文件示例代码
/**
* 下载文件
* @param fs 客户端对象
* @param src 待下载的文件门路,也就是 HDFS 上的文件门路
* @param dst 指标门路
*/
public static void downFile(FileSystem fs, Path src, Path dst){
try {fs.copyToLocalFile(false,src,dst);
} catch (IOException e) {e.printStackTrace();
}
}
2 读写流程
2.1 写文件流程
通过代码实现了文件上传,那么这两头 HDFS 是怎么实现文件的写入的呢?
流程如下图所示:
途中蕴含以下角色
Client、Distributed FileSystem、FSData InputStream、NameNode、DataNode,除了 Distributed FileSystem、FSData InputStream 两个角色外,其余曾经在之前说过。
Distributed FileSystem,翻译过去就是分布式文件系统。
FSDataOutputStream 就是一个输入流对象。
1)Client 向 HDFS 写数据的时,文件是分块存储在 HDFS 的各个 DataNode 节点上,而存储地位的是 NameNode 规定的,所以 Client 在上传文件时须要先和 NameNode 进行交互。
Client 首先调用 Distributed FileSystem 的 create 办法,而后近程调用 NameNodeNode 的 create()。
NameNode 的查看是否已存在文件、查看权限。若通过查看,间接先将操作写入 Edits 文件 Client,返回 FSDataOutputStream。
2)Client 开始切分文件,申请上传,而后从 NameNode 获取上传到的 DataNode 节点信息,假设是 d1,d2,d3 三个节点。
3)client 通过 FSDataOutputStream 对象调用 write()写数据,具体流程如下:
申请 dn1 上传数据,d1 收到申请会持续调用 d2,而后 d2 调用 d3,实现传输通道的建设。
4)client 向 d1 上传第一个 block(从磁盘读取数据先放到一个本地内存缓存),以 Packet 为单位,d1 收到一个 Packet 就会传给 d2,d2 传给 d3;d1 每传一个 packet 会放入一个应答队列期待应答。
5)当实现整个文件的写入后,执行 FSDataOutputStream 的 close()办法,同时告知 NameNode 我实现了文件写入操作。
2.2 读文件流程
同样 client 通过 Distributed FileSystem 向 NameNode 申请下载文件,NameNode 查问元数据失去下载文件所在的 DataNode 节点信息。
存储该文件的节点有很多,会优先选择一个最近的节点,发动申请。
DataNode 开始传输数据给客户端。
Client 以 Packet 为单位接管,先在本地缓存,而后写入指标文件。