HDFS pipeline写 -- 客户端
上一篇说了datanode端如何处理pipeline写请求的,这里主要看DFSClient。
这里以append为例, write差不多。
创建一个pipeline用于append操作的流程:
FileSystem.get(configuration) 返回一个已经初始化完成的DistributedFileSystem对象,内部包含一个DFSClient对象
DistributedFileSystem.append(Path)内部调用DFSClient的append方法返回一个FSDataOutputStream(实际是HdfsDataOutputStream)
,应用往这个stream中write数据即可。
看看DFSClient.append()做了什么
调namenode.getFileInfo(file)向namenode得到file的相关信息,包括文件长度,
mtime,atime,block_size,是否为目录,权限,owner,group等.调namenode.append(file,clientName)获取file最后一个block的位置信息,以LocatedBlock形式返回.具体看看这个函数.
2.1 namenode内部调用FSNameSystem的appendFile(file, clientName)
从FSDirectory中拿到file对应的INode,做一些check,比如权限,file是文件,不是目录等。
然后调用recoverLeaseInternal检查是否file需要recover lease,详细看看这个函数:
从INodeFile可以知道这个文件是否处于under construction状态,如果不是,则说明不需要进 行lease recovery. 如果是,那么从LeaseManager拿到clientname对应的Lease,以及file所在的Lease,检查是否这个file的Lease已经被当前clientname持有,如果是,则抛异常,客户端append失败。否则,从INodeFile中拿到当前file的lease holder
,然后去LeaseManager中根据lease holder拿到Lease,然后判断Lease是否过期(lease最后更新时间离现在已经超过soft limit,默认60s)。如果没有过期,说明当前文件的lease正被别人持有,不能进行append,抛异常,客户端append失败.如果过期,开始
进入lease recovery阶段, 执行internalReleaseLease(),函数的目的就是使这个file的最后一个block的所有副本数据一致,副本数据不一致可能由之前写这个文件的客户端意外宕机导致。这个问题后续专门分析。2.2 检查最后一个block是否副本数足够,如果不足够,同样抛异常,客户端失败。
2.3 将INodeFile设置为under construction状态,将clientname作为lease holder设置到INodeFile中。同时将clientname,filename添加到Lease中。
2.4 从INodeFile拿出最后一个block的BlockInfo,如果block已经满了,则返回null,后续客户端会发addBlock请求给namenode申请block进行append。如果block不满,将最后一个block设置为under construction状态。更新blocksMap.最后,将最后一个block的LocatedBlock返回给DFSClient.
构造DFSOutputStream对象,并且启动对象内部的DataStreamer线程,这里会根据上一步的LocatedBlock来设置DataStreamer的stage状态,显然,如果上一步返回的LocatedBlock不为空,说明append的最后一个block没有满,则stage设置为PIPELINE_SETUP_APPEND,isAppend设置为true,如果LocatedBlock为空,则stage设置为PIPELINE_SETUP_CREATE,isAppend设置false,在这种情况下,会调用nextBlockOutputStream函数来建立pipeline,内部会调用addBlock()向namenode申请一个新的block用于append。最后返回一个包装了DFSOutputStream的HdfsDataOutputStream的对象给客户端.
客户端拿到HdfsDataOutputStream后,往流里写数据,数据以packet的形式被放如DataStreamer
的dataQueue中。DataStreamer线程就是建立pipeline后,往pipeline中写一个个packet,最后关闭pipeline.
对于append来说,建立pipeline的函数是setupPipelineForAppendOrRecovery,函数内部会处理
建立pipeline过程中的失败和重试,最后函数的返回值就代表pipeline是否建立成功.
下面看setupPipelineForAppendOrRecovery是如何建立pipeline和建立失败时pipeline的重试工作.
DFSOutputStream中的DataStreamer建立pipeline时,如果出现某个坏的datanode,那么pipeline会断掉,例如client->A->B->C,B给C建立pipeline时,C是一个坏的datanode,那么在B的DataXceiver.writeBlock()中会设置BlockOpResponseProto的firstBadLink,然后回复给A,A收到后,主动断开和B的连接,以此类推。
pipeline建立失败会将这个第一个坏的datanode踢出pipeline并且放入到一个失败集合中.然后对剩下的datanode检查是否满足了replace-datanode policy,简单来说,就是检查是否需要新增一个datanode进来构成新的pipeline集合,是否需要增加新的datanode进来,主要考虑几个因素, 副本数,是否执行的hflush,是否append操作,当前pipeline中datanode个数.如果最后判定需要新增加datanode,会调用getAdditionalDatanode请求namenode重新分配一个datanode,这里会将失败集合发给namenode,namenode这次不会再选择这些坏的datanode.随后调updateBlockForPipeline向namenode重新申请这个block的新的generation stamp和token.然后调用createBlockOutputStream()重新建立pipeline.一旦建立pipeline成功,会调用updatePipeline向namenode更新pipeline,将旧block和新block的信息发给namenode,namenode根据旧block信息从BlockManager中找到对应的BlockInfo,确定其处于UNDER_CONSTRUCTION状态,并且从BlockInfo中拿出这个Block所在的HDFS文件对应的inode结构INodeFile,并且确定file处于under construction状态,并且确定从INodeFile拿出的clientname和传进来的clientname是相等的。然后,从INodeFile中取出最后一个BlockInfo,将其cast成BlockInfoUnderConstruction,然后再次进行check,如果新block的generation stamp小于等于最后一个block的generation stamp,或者字节数小于最后一个block的generation stamp,那么抛异常.否则更新最后一个block的字节数和generation stamp为新BlockInfo的值,并且设置好最后一个block的List replicas属性,每个replica的状态设置为RBW.
pipeline 建立好后,DataStreamer启动ResponseProcessor线程用于处理下游对packet的ack,接着DataStreamer从dataQueue中取出一个个的packet往pipeline发.最后拆除pipeline.
参考资料
hadoop-hdfs-2.4.1.jar
HDFS pipeline写 -- 客户端的更多相关文章
- HDFS pipeline写 -- datanode
站在DataNode的视角,看看pipeline写的流程,本文不分析客户端部分,从客户端写数据之前拿到了3个可写的block位置说起. 每个datanode会创建一个线程DataXceiverServ ...
- 2 weekend110的HDFS的JAVA客户端编写 + filesystem设计思想总结
HDFS的JAVA客户端编写 现在,我们来玩玩,在linux系统里,玩eclipse 或者, 即,更改图标,成功 这个,别慌.重新换个版本就好,有错误出错是好事. http://www.eclips ...
- HDFS的写数据过程分析
HDFS的写数据过程分析 我们通过FileSystem类可以操控HDFS, 那我们就从这里开始分析写数据到HDFS的过程. 在我们向 HDFS 写文件的时候,调用的是 FileSystem.creat ...
- 一脸懵逼学习hadoop之HDFS的java客户端编写
1:eclipse创建一个项目,然后导入对应的jar包: 鼠标右击项目,点击properties或者alt+enter快捷键--->java build path--->libraries ...
- 一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse)
一次失败的尝试hdfs的java客户端编写(在linux下使用eclipse) 给centOS安装图形界面 GNOME桌面环境 https://blog.csdn.net/wh211212/artic ...
- day03-hdfs的客户端操作\hdfs的java客户端编程
5.hdfs的客户端操作 客户端的理解 hdfs的客户端有多种形式: 1.网页形式 2.命令行形式 3.客户端在哪里运行,没有约束,只要运行客户端的机器能够跟hdfs集群联网 文件的切块大小和存储的副 ...
- Linux启动kettle及linux和windows中kettle往hdfs中写数据(3)
在xmanager中的xshell运行进入图形化界面 sh spoon.sh 新建一个job
- HDFS的Java客户端编写
总结: 之前在教材上看hdfs的Java客户端编写,只有关键代码,呵呵…….闲话不说,上正文. 1. Hadoop 的Java客户端编写建议在linux系统上开发 2. 可以使用eclipse,ide ...
- 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-9.使用JWT生成用户Token回写客户端
笔记 9.使用JWT生成用户Token回写客户端 简介:讲解用户授权登录后,需要生成登录凭证重定向到页面上 1.获取当前页面访问地址 2.根据User基本信息生成token 3.重定向到指定页 ...
随机推荐
- 【数组】Search a 2D Matrix
题目: Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the f ...
- Android4.0 Launcher 源码分析2——Launcher内容加载绑定详细过程
Launcher在应用启动的时候,需要加载AppWidget,shortcut等内容项,通过调用LauncherModel.startLoader(),开始加载的工作.launcherModel中加载 ...
- Android_Universal-Image-Load使用
一,快速使用(确保ImageLoader只初始化一次,这样图片缓存会更加优秀.) 场景:为ImageView设置一张指定Uri的图片. 1,导包,配置联网,读写SD卡权限. 2,初始化: ImageL ...
- Java并发编程笔记之ThreadLocalRandom源码分析
JDK 并发包中 ThreadLocalRandom 类原理剖析,经常使用的随机数生成器 Random 类的原理是什么?及其局限性是什么?ThreadLocalRandom 是如何利用 ThreadL ...
- OOAD之创建型模式之工厂模式
首先我们为什么要学习设计模式呢? 1)模式从经验中总结出来的,经过证实的方案,模式只有在实际系统中经过多次验证之后才能成为模式. 2) 提高系统的可维护性, 通过使用设计模式,在系统面临升级和维护时, ...
- KafkaOffsetMonitor监控kafka
KafkaOffsetMonitor监控kafka 1. KafkaOffsetMonitor是一个可以用于监控Kafka的Topic及Consumer消费状况的工具,其配置和使用特别的方便.源项目G ...
- Hadoop+Hive 操作mongodb数据
Hadoop+Hive 操作mongodb数据 1.版本概述 hadoop-2.7.3.hive-2.2 下载响应的jar包:http://mvnrepository.com/,直接搜索想要的jar包 ...
- 展示博客(Alpha阶段)
Deadline: 2017-11-18 22:00PM,以博客发表日期为准 评分基准: 按时交 - 有分(满分10分),检查的项目包括后文的四个方面 团队成员介绍 Alpha阶段进展 团队合作,各成 ...
- 破解栅栏密码python脚本
今天遇到一个要破解的栅栏密码,写了个通用的脚本 #!/usr/bin/env python # -*- coding: gbk -*- # -*- coding: utf_8 -*- # Author ...
- 在懒加载的Ionic工程中使用 ionic2-auto-complete 组件:Can't bind to 'dataProvider' since it isn't a known property of 'ion-auto-complete'
问题描述: 在基于懒加载的Ionic工程中,使用ionic2-auto-complete组件(GitHub地址:https://github.com/kadoshms/ionic2-autocompl ...