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为单位接管,先在本地缓存,而后写入指标文件。