14. Hadoop RPC框架之客户端Stub

客户端的Stub可以看作是一个代理对象,它会将请求程序的RPC调用序列化,并调用Client.call()方法将这个请求发送给远程服务器,这些请求对于对于客户端调用程序是完全透明的。

客户端Stub程序做的第一件事就是将RPC请求序列化,Hadoop 2.X默认使用protobuf作为序列化工具,当然Hadoop RPC框架也支持其他的序列化框架。Hadoop定义了RpcEngine接口抽象使用不同序列化框架的RPC引擎,接下来看RpcEngine的两个重要的方法,getProxy()和getServer()

RpcEngine的两个重要的方法

首先看下RpcEngine具有的方法,如下图所示

13274599-408e777f7e594969.png
13. RpcEngine具有的方法.png

首先看下getProxy()方法

客户端会首先调用RpcEngine.getProxy()方法获取一个本地接口的代理对象,然后在这个代理对象上调用本地接口的方法。getProxy()方法的实现采用了Java动态代理机制,客户端调用程序在代理对象上的调用会由一个RpcInvocationHandler(java.lang.reflect.InvocationHandler的子类,在RpcEngine的实现类中定义)对象处理,这个RpcInvocationHandler会将请求序列化(使用RpcEngine实现类定义的序列化方式)并调用Client.call()方法将请求发送到远程服务器。当远程服务器发回相应信息后,RpcInvocationHandler会将相应信息反序列化并返回给调用程序,这一切通过Java动态代理机制对于调用程序是完全透明的,就像本地调用一样

接下来看下getServer()方法

该方法用于产生一个RPC Server对象,服务器会启动这个Server对象监听从客户端发来的请求。成功从网络接收请求数据后,Server对象会调用RpcInvoker(在RpcEngine的实现类中定义)对象处理这个请求

RpcEngine的子类

RpcEngine目前有两个子类,其中WritableRpcEngine用于描述使用Hadoop自带的Writable作为序列化工具的RPC引擎,ProtobufRpcEngine用户描述使用protobuf作为序列化工具的RPC引擎,WritableRpcEngine和ProtobufRpcEngine都定义了若干内部类,下图是RpcEngine继承结构图

13274599-a1b5baed52bee8e1.png
14. RpcEngine继承结构图.png

下面简单介绍下这些类的作用

WritableRpcEngine

Invoker:WritableRpcEngine.Invoker是InvocationHandler的子类(Java动态代理框架中的处理类)。客户端会首先调用WritableRpcEngine.getProxy()获取一个本地接口(例如ClientProtocol)的代理对象,然后在这个代理对象上调用本地接口的方法。通过Java动态代理机制的处理,这个调用会被WritableRpcEngine.Invoker类的invoke()方法响应。WritableRpcEngine.Invoker.invoke()方法会使用Writable序列化框架将RPC请求以及参数序列化,然后构造一个Invocation对象(WritableRpcEngine的子类,实现了Writable接口)包装序列化的RPC请求及参数,最后调用Client.call()方法将这个Invocation对象发送到远程服务器,并等待远程服务器的响应信息。成功获取了服务器发回的响应信息后,Invoker会将响应信息反序列化并返回给客户端。

Invocation:Client.call()方法只能发送Writable类型的RPC请求,这样定义是为了让发送接口更通用,不同框架序列化的请求只需包装成一个Writable对象就可以通过Client发送。这里的Invocation内部类就是为了包装Writable的RPC请求,它保存了客户端在什么接口上调用什么方法,以及这个方法的参数等调用信息。Invoker构造了Invocation对象之后,就会调用Client.call()方法将这个对象发送到远程服务器。

Server:WritableRpcEngine.Server是org.apache.hadoop.ipc.Server类的子类,服务器代码会调用WritableRpcEngine.getServer()方法获取一个WritableRpcEngine.Server对象,WritableRpcEngine.Server类继承了org.apache.hadoop.ipc.Server大部分方法,它会在Socker上监听RPC请求,并调用WritableRpcEngine类的call()方法响应这个请求

WritableRpcInvoker:WritableRpcInvoker是WritableRpcEngine.Server的内部类,它实现了RpcInvoker接口,用于响应远程客户端的请求。WritableRpcInvoker会先使用Writable序列化工具反序列化请求信息以及请求参数,然后根据请求信息反射调用服务程序,并将响应结果包装成一个Writable对象返回

ProtobufRpcEngine

Invoker:与WritableRpcEngine.Invoker类相同,都是用于处理客户端发送RPC请求的,不同处有4点,①RPC请求信息及请求参数序列化使用了protobuf工具;②使用RpcRequestWrapper类包装RPC请求(包括请求信息及请求参数);③使用RpcResponseWrapper类包装④

RpcRequestWrapper:Client.call()方法只接受Writable类型的RPC请求,而ProtobufRpcEngine.Invoker是使用protobuf序列化RPC请求的,这里就需要一个包装类RpcRequestWrapper将protobuf格式的请求包装成Writable类型。RpcRequestWrapper保存了两部分信息,这两部分信息都是使用protobuf序列化的,①是RPC请求头,RPC请求头记录了客户端在什么接口上调用了什么方法;②请求参数,方法调用的参数。Invoker类构造了RpcRequestWrapper对象后,会调用Client.call()方法将这个请求发送到远程服务器。

RpcResponseWrapper:Client.call()方法返回的响应信息也是Writable类型的,但是服务器端使用了protobuf序列化RPC响应信息,这就需要定义一个包装类RpcResponseWrapper将这个protobuf序列化的响应信息包装成Writable类型

Server:与WritableRpcEngine.Server类功能类似,它会在Socket上监听RPC请求,并调用ProtoBufRpcInvoker类的call()方法响应这个请求

ProtoBufRpcInvoker:与WritableRpcInvoker类功能类似,用于响应远程客户端的请求,不同之处有如下几点,①使用了protobuf这个序列化工具;②使用了RpcRequestWrapper类包装RPC请求(包括请求信息以及请求参数);③使用了RpcResponseWrapper类包装服务器发回的RPC响应信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值