Hadoop-组件-HDFS-源码学习-RPC 通信服务-协议层设计
一、概述
RPC 协议是使用 Hadoop RPC 框架的第一步,HDFS 为各个节点之间抽象了不同的 RPC 协议,例如 ClientProtocol 抽象了客户端与名字节点之间的通信协议,HDFS 客户端调用 ClientProtocol.rename() 方法,Namenode 服务器就会更改指定 HDFS 文件的文件名。而 DatanodeProtocol 则抽象了数据节点与名字节点之间的通信协议。
1.1. 协议栈
对于 HDFS 中的所有 RPC 协议,都会存在一个如图所示的协议栈:
对于 ClientProtocol,存在对应的支持序列化的接口 ClientNamenodeProtocolPB,同时还存在 ClientNamenodeProtocolTranslatorPB 以及 ClientNamenodeProtocolServerSideTranslatorPB 两个类用于进行协议适配
二、实现
2.1. ClientProtocol 协议
ClientProtocol 协议定义了 HDFS 客户端与 Namenode 交互的所有接口方法(例如 rename()、mkdir()等)
2.1.1. 结构
- ClientNamenodeProtocolTranslatorPB 这个类是 RPC 客户端侧最重要的类之一,将客户端的请求参数封装成可以序列化的 protobuf 格式,然后通过代理类(实现了 ClientNamenodeProtocolPB 接口的代理类)发送出去。
- NameNodeRpcServerNamenode 侧响应 ClientProtocol 调用的类,它会执行 HDFS 操作并将操作结果返回。
2.2. ClientNamenodeProtocolPB 协议
ClientProtocol 是 HDFS 客户端与名字节点之间的接口,但是在 RPC 调用中,RPC 方法的参数和返回值都必须是可序列化的,HDFS 定义了一个新的 ClientNamenodeProtocolPB 协议对 ClientProtocol 协议中方法的参数和返回值进行包装。
ClientNamenodeProtocolPB 协议定义的方法与 ClientProtocol 一样,但是参数和返回值使用 protobuf 序列化后的格式,这样ClientNamenodeProtocolPB 请求就可以通过网络传输。
Hadoop RPC 使用了 protobuf 工具,定义 ClientNamenodeProtocol.proto 文件,将 ClientProtocol 的参数抽象为一个 *RequestProto
对象,而将返回值抽象为一个 *ResponseProto
对象。
以 rename() 方法为例,ClientNamenodeProtocol.rename()方法的参数是 RenameRequestProto,返回值是 RenameResponseProto。RenameRequestProto 和 RenameResponseProto 是 protobuf 定义的用于封装客户端请求参数以及服务端返回值的类,其结构也是在ClientNamenodeProtocol.proto 文件中定义。
2.3. 适配器类
ClientNamenodeProtocolTranslatorPB 类是 RPC Client 侧的适配器类,ClientNamenodeProtocolServerSideTranslatorPB 则是 RPC Server 侧的适配器类。
2.3.1. 客户端
Client 侧的适配器用于将 ClientProtocol 的请求转换为 ClientNamenodeProtocolPB 请求。
DFSClient 持有一个 ClientNamenodeProtocolTranslatorPB 类的引用,用于将 ClientProtocol 协议上的请求适配成 ClientNamenodeProtocolPB 协议的请求。ClientNamenodeProtocolTranslatorPB 将 ClientProtocol 请求的参数序列化,调用 rpcProxy 对象(实现了 ClientNamenodeProtocolPB 接口)上的对应方法,完成适配操作。
以 rename()方法调用作为例子,ClientNamenodeProtocolTranslatorPB 执行了两个操作来完成 ClientProtocol.rename()调用的适配功能。
2.3.2. 服务端
Server 侧的适配器则是将 ClientNamenodeProtocolPB 请求转换为 ClientProtocol 请求。
ClientNamenodeProtocolServerSideTranslatorPB 将 ClientNamenodeProtocolPB 请求的参数反序列化,然后在 ClientProtocol 服务对象 server 上调用对应的方法即可完成适配工作。
以 rename() 方法为例,ClientNamenodeProtocolServerSideTranslatorPB.rename()会首先反序列化请求参数 RenameRequestProto 对象,然后调用 server 对象的 rename() 方法执行重命名操作,最后将返回值序列化为 RenameResponseProto 对象并返回。