RPC3

2.4 服务端获取服务对象server

Namenode会在它的初始化方法initialize()方法中调用createRpcServer()方法创建NameNodeRpcServer对象的实例。createRpcServer()方法会直接调用NameNodeRpcServer的构造方法。

NameNodeRpcServer的构造方法很长,因为它实现了多个接口,如果我们只关注与ClientProtocol相关的代码,则构造方法中的流程可以分为两个部分:

  • 获取响应ClientNamenodeProtocolPB请求的BlockingService对象。

ClientNamenodeProtocolServerSideTranslatorPB
   clientProtocolServerTranslator =
    
new ClientNamenodeProtocolServerSideTranslatorPB(this);
 BlockingService clientNNPbService = ClientNamenodeProtocol.
     newReflectiveBlockingService(clientProtocolServerTranslator)
;

  • 构造Server对象: serviceRpcServer。

下面分别就获取BlockingServiceService对象和构造Server对象展开介绍。

2.4.1 获取BlockingService对象

       ClientNamenodeProtocolServerSideTranslatorPB是将ClientNamenodeProtocolPB接口调用适配成ClientProtocol调用的适配器类(作用可以类比客户端的ClientNamenodeProtocolTranslatorPB),它内部会持有一个实现了ClientProtocol接口的对象,将ClientNamenodeProtocolPB调用的参数反序列化之后,它会调用ClientProtocol对象的对应方法执行RPC操作。通过NameNodeRpcServer构造方法的代码我们知道,ClientNamenodeProtocolServerSideTranslatorPB中持有的ClientProtocol接口对象其实就是NameNodeRpcServer,NameNodeRpcServer实现了ClientProtocol接口,是Namenode RPC服务真正的实现类。

       ClientNamenodeProtocol.newReflectiveBlockingService()方法会构造一个匿名的BlockingService对象并返回,这个匿名的BlockingService对象定义了一个callBlockingMethod()方法。callBlockingMethod()方法接收三个参数:method参数描述了当前RPC调用的方法信息;controller参数在这里默认为null,不使用;request参数记录了RPC调用的参数信息。callBlockingMethod()方法会根据method参数记录的调用方法信息,在ClientNamenodeProtocolServerSideTranslatorPB引用上调用对应的方法。这样,Server对象监听到RPC请求后,只需通过请求信息中的接口信息获取对应的BlockingService对象,然后在这个BlockingService对象上调用callBlockingMethod()就可以触发NameNodeRpcServer对象响应这个RPC请求了。

2.4.2 构造Server对象

this.serviceRpcServer = new RPC.Builder(conf)
    .setProtocol(
        org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolPB.
class)
    .setInstance(clientNNPbService)
    .setBindAddress(bindHost)
    .setPort(serviceRpcAddr.getPort()).setNumHandlers(serviceHandlerCount)
    .setVerbose(
false)
    .setSecretManager(
namesystem.getDelegationTokenSecretManager())
    .build()
;

      

NameNodeRpcServer构造方法中通过RPC.Builder.build()构造了serviceRpcServer。build()方法代码如上所示,它设置了protocol参数为ClientNamenodeProtocolPB.class,同时设置了impl参数为clientNNPBService。这两个参数设置了ClientNamenodeProtocolPB协议与它的BlockingService响应类的对应关系。

build()方法首先调用getProtocolEngine()方法获取当前RPC类配置的RpcEngine对象,在NameNodeRpcServer的构造方法中已经将当前RPC类的RpcEngine对象设置为ProtobufRpcEngine了,获取了ProtobufRpcEngine对象之后,build()方法会在ProtobufRpcEngine对象上调用getServer()方法获取一个RPC Server对象的引用。这里的RPC.Server对象是ProtobufRpcEngine的内部类Server。

在gerServer()方法内部会调用ProtobufRpcEngine.Server的构造方法,ProtobufRpcEngine.Server的构造方法首先调用父类RPC.Server的构造方法,之后构造方法会调用registerProtocolAndImpl()方法注册接口类protocolClass和实现类protocolImpl的映射关系。这样,当客户端的RPC请求到达时,就可以通过这个映射关系获得具体的实现类了。

ProtobufRpcEngine.Server类最重要的部分就是实现了一个ProtoBufRpcInvoker类,当RPC.Server类解析楚来自网络的RPC请求后,会调用ProtoBufRpcInvoker.call()方法响应这个请求。这里我们重点看一下call()方法的实现。call()方法首先会从请求头中提取出RPC调用的接口名和方法名等信息,然后根据调用的接口信息获取对应的BlockingService对象,再根据调用的方法信息在BlockingService对象上调用callBlockingMethod()方法并将调用前转到ClientNamenodeProtocolServerSideTranslatorPB对象上,最终这个请求会由NameNodeRpcServer响应。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值