深入理解 HDFS(三):Hadoop RPC
TCP/IP 是一种面向连接的、可靠的、基于字节流的传输层通信协议,Hadoop RPC 通信协议是建立在 TCP/IP 协议之上,自己实现的一套 RPC 协议。那 Hadoop RPC 是如何从设计到实现的呢,以下是我个人理解,不对之处欢迎指出。
1. RPC 目的
在使用面向对象语言编程时,如果想使用某个类的具体功能,需要先创建这个类的对象,之后调用对象提供该功能的方法,一切看起来非常自然。由此推断 RPC 也是同样目的:调用远程服务可以像调用本地对象的方法那样简单,忽略底层的通信模型。专注于功能的实现。
2. 抽象设计
服务端提供服务,客户端调用服务,请求的调用如果能委托一个第三方 Invoker,那么通信的角色有:
Client:获取服务端提供的功能;
Invoker:通过某种机制将 Client 请求传递给 Server,同时 Server 处理后将结果返回给 Client;
Server:提供不同类型的一系列功能。
Server 需要解析 Client 发送的各种请求,处理后需要将相应结果返回给 Client,所以调用的流程应该是:
Client -> 请求对象创建 -> 请求对象序列化 -> Invoker 调用 -> 请求对象反序列化 -> Server 处理请求 -> 响应对象创建 -> 响应对象序列化 -> Invoker 中转 -> 响应对象反序列化 -> Client 解析响应
而在 HDFS 中类的设计:
Call:Client 创建的请求;
Message:Server 处理请求返回的响应结果;
RpcWritable:序列化和反序列化依赖的中间结果。
3. 具体实现
在序列化和反序列化的开源项目中,Google 的 Protobuf 首屈一指,那么 Protobuf 用于 RPC 协议的实现是一个不错的选择,下面是 Hadoop RPC 的大致实现:
实际请求和响应都使用 Protobuf 对象,请求对应着 RequestProto,响应对应着 ResponseProto;
如果 Client 端基于 DistributedFileSystem,那么请求最终会通过 DFSClient 发送;
ProtobufRpcEngine2 的内部类 ProtoBufRpcInvoker 实现了 RpcInvoker,获取实际请求的处理类并转发请求;
Server 最终转化成多个 BlockingService,每个 BlockingService 提供某类具体功能。
4. Hadoop RPC 协议格式
Hadoop RPC 的协议主要由三部分组成:
头信息:用以标识此次是 RPC 请求,前 4 个字节是魔数 hrpc;
连接上下文信息:请求头 + 具体内容;
实际请求数据:Protobuf 请求头和数据。
为了查看实际协议内容,写了一段用于获取 HDFS 目录详情的代码,先前已经创建了 /tmp 目录。
程序执行时,服务端使用 tcpdump 进行抓包,之后将包下载到本地,用 wireshark 打开分析:
101.241.83.234 是我的客户端 IP,10.0.16.6 是 Namenode IP,前三行是 TCP 的三次握手,第 4 行是通过调用fileSystem.getFileStatus
发送的请求, TCP 的 data (200 bytes) 就是此次发送的 bytes,下面让我们根据协议格式的定义,结合实际数据来分析:
版权声明: 本文为 InfoQ 作者【冰心的小屋】的原创文章。
原文链接:【http://xie.infoq.cn/article/ad5b9e30a0d963ebe6ba1da5f】。文章转载请联系作者。
评论