Hadoop RPC接口主要是定义在org.apache.hadoop.hdfs.server.protocol和org.apache.hadoop.hdfs.protocol两个包中。其中主要包括如下几个接口:
- // 客户端从hdfs得到对应数据块在datanode的位置,按由远到近的距离进行排序返回给客户端
- LocatedBlocks getBlockLocations(String src, long offset, long length)
- // 客户端向namenode回报错误块,当客户端读取数据块发现数据校验和不正确的时候
- void reportBadBlocks(LocatedBlock[] blocks) throws IOException;
- // 用于在hdfs上面创建一个src路径的空文件夹,创建的时候对于其他的客户端是可读的,
- // 直到文件关闭或者租约过期,然后通过addBlock()方法获取存储块的位置信息,
- // 最后客户端就可以更具这些位置信息建立数据通道,就可以传数据了
- HdfsFileStatus create(String src, FsPermission masked,
- String clientName, EnumSetWritable<CreateFlag> flag,
- boolean createParent, short replication, long blockSize,
- CryptoProtocolVersion[] supportedVersions, String ecPolicyName)
- throws IOException;
- // 如果最后一个数据块没有写满返回数据块的信息,如果写满了,那么就调用create()
- LastBlockWithStatus append(String src, String clientName,
- EnumSetWritable<CreateFlag> flag) throws IOException;
- // 客户端先指定的文件添加一个数据块信息,并且返回这个数据块所有数据节点的位置信息
- LocatedBlock addBlock(String src, String clientName,
- ExtendedBlock previous, DatanodeInfo[] excludeNodes, long fileId,
- String[] favoredNodes, EnumSet<AddBlockFlag> addBlockFlags)
- throws IOException;
- // 当客户端上传的文件所有的数据块上传完毕,会调用complete()通知namenode,并且满足最小的副本数是1的时候那么返回true
- boolean complete(String src, String clientName,
- ExtendedBlock last, long fileId)
- throws IOException;
上面5个方法是客户端写文件必须调用的方法。
下面的方法是异常的情况
- // 当客户端上传文件时发现这个数据块的数据节点无法建立连接的时候会调用abandonBlock()
- // 并且返回不能建立连接的数据块给namenode避免下一次分配到
- void abandonBlock(ExtendedBlock b, long fileId,
- String src, String holder)
- throws IOException;
命名空间管理的相关方法
集群的安全模式方法
- // 在namenode满足数据块最小副本数据块达到一定比例之前,不接受客户端的请求,也不会触发datanode
- // 任何副本的复制
- boolean setSafeMode(HdfsConstants.SafeModeAction action, boolean isChecked)
- throws IOException;
ClientDatanodeProtocol主要是客户端和datanode通信,它的方法相对于比较简单,如下
- // 获取文件的真实长度
- long getReplicaVisibleLength(ExtendedBlock b) throws IOException;
- // 读取文件的优化,作用是在读取文件的时候先查看本地有没有
- BlockLocalPathInfo getBlockLocalPathInfo(ExtendedBlock block,
- Token<BlockTokenIdentifier> token) throws IOException;
- // 使得datanode重新的加载配置文件,删除停止使用的块池文件
- void refreshNamenodes() throws IOException;
- // 删除对应的块池
- void deleteBlockPool(String bpid, boolean force) throws IOException;
- // 关闭数据节点
- void shutdownDatanode(boolean forUpgrade) throws IOException;
- // 得到datanode的信息
- DatanodeLocalInfo getDatanodeInfo() throws IOException;
- // 触发datanode异步加载配置
- void startReconfiguration() throws IOException;
datanode会使用这个接口先namenode发送握手,注册,心跳,进行全量或增量数据汇报,一个完整的启动操作有下面的4个步骤
versionRequest()主要的作用就是获取namenode的信息比如集群信息,版本信息,数据块池信息,然后datanode会对比自己的信息是否匹配,如果匹配那么就握手成功
datanode调用registerDatanode()汇报自己的信息给namenode,然后调用blockReport()汇报自己的块信息
如果出现读取文件错误的时候,client会通过DFSInputStream读取下 一个节点的信息,注意,读取文件的时候除了有数据块的信息以外,还有数据的校验信息,如果client读取到的数据的校验信息错误时,client会通过ClientProtocol.reportBadBlocks()汇报给namenode错误块的信息,使得namenode会删除对应错误的副本,创建新的副本
介绍完读流程以后,我们来看一下客户端的写流程
如果在写入的过程中发生了错误,client会断开连接,并且汇报给namenode建立新的连接
上面介绍了客户端的流程,下面介绍datanode和namenode的交互流程
Datanode启动后与Namenode的交互主要包括三个部分:①握手;②注册:③块汇报以
及缓存汇报。
HDFS的高可用(High Availability,HA)方案就是为了解决上述问题而产生的,在HA HDFS集群中会同时运行两个Namenode,一个作为活动
的(Active)Namenode,一个作为备份的(Standby)Namenode。Active Namenode的命名空
间与Standby Namenode是实时同步的,所以当Active Namenode发生故障而停止服务时,
Standby Namenode可以立即切换为活动状态,而不影响HDFS集群的服务。
RPC框架的结构,主要包括以下几部分。
图2-6给出了DFSClient调用ClientProtocol.rename()方法的流程图。我们首先看一下RPC
协议的定义部分。ClientProtocol协议定义了HDFS客户端与名字节点交互的所有方法,但是
ClientProtocol协议中方法的参数是无法在网络中传输的,需要对参数进行序列化操作,所以
HDFS又定义了ClientNamenodeProtocolPB协议。ClientNamenodeProtocolPB协议包含了
ClientProtocol定义的所有方法,但是参数却是使用protobuf序列化后的格式。这里还是以
rename()方法为例,ClientNamenodeProtocolPB将ClientProtocol中rename(String,String)方法
的两个参数抽象成一个RenameRequestProto对象,rename()方法的签名也就变成了
renamet(RenameRequestProto)。这里的RenameRequestProto对象是通过protobuf序列化后的对
象,是可以在网络上传输的对象。