怎么看调用的接口_Hadoop RPC调用实例分析

以ClientProtocol接口中的rename RPC调用进行一次实例分析。

rename方法在ClientProtocol接口中定义,它的两个参数是String类型的,不能直接通过网络传输。

1e7202945d4d44449e09fa25124cb21e.png

我们看谁实现了ClientProtocol接口并重写rename方法。

fd6b0b0f8e0daf16c6c9f13345a98e20.png

看到是ClientNamenodeProtocolTranslatorPB这个类。看下这个类如何实现的rename方法,代码如下:

  @Override
  public boolean rename(String src, String dst) throws IOException {
      //把String类型的参数进行包装,变成可通过网络传输的序列化类型
    RenameRequestProto req = RenameRequestProto.newBuilder()
        .setSrc(src)
        .setDst(dst).build();

    try {
        //通过调用rpcProxy的rename方法实现rpc调用,接下来我们就看rpcProxy这个对象
      return rpcProxy.rename(null, req).getResult();
    } catch (ServiceException e) {
      throw ProtobufHelper.getRemoteException(e);
    }
  }

rpcProxyClientNamenodeProtocolTranslatorPB这个类的成员变量,类型是ClientNamenodeProtocolPB

beeba28b69fb4546cdb17f95979c9546.png

那我们就继续点进去rpcProxy.rename方法。发现点不进去了,因为rpcProxy的类型是ClientNamenodeProtocolPB。这个类继承了protoBuf生成的类,我们还没有编译所以点不进去。

f60ce2b11d231f2557287a28649300e5.png

但是可以看看相关的.proto文件。找到ClientNamenodeProtocol.proto文件,搜索rename。能够看到protobuf定义的参数和返回值。参数就是把原本的两个字符串类型包装成新的RenameRequestProto类型。

b5cc83a8dd0df1bda97bd85cd7168ceb.png
7bc1b067d3ba3095894b7e697c772436.png

似乎我们是没法往下看了。感觉也没什么收获?那你感觉错了。我们还可以看看ClientNamenodeProtocolTranslatorPB的构造函数,看看是怎么初始化的rpcProxy对象。

569c3315408a60dc37a807ec97ffebae.png

继续追,看看谁调用了这个构造函数。

90d47ef7046d9af96d2a2b962908c9b1.png

这三处地方调用了。我们进入第一个方法:

86ffd52a96864e8f57d40aa37f7f9e6d.png

我们继续看这个proxy是怎么生成的。

33d17df4e84dea4e41ef3929346bab26.png

这是一个链式调用。先调用了RPC.getProtocolProxy,然后调用了getProxy()。

调用getProtocolProxy得到一个ProtocolProxy< ClientNamenodeProtocolPB>对象,这个对象包含了用于和服务端通信的代理对象和服务端支持的方法集合。在这个对象的基础上调用getProxy方法得到那个代理对象。

RPC.getProtocolProxy()的代码如下:

bbd1901e33c83e124bfcca6a7f330c20.png

可以看到首先调用了getProtocolEngine获得通信所使用的RpcEngine,然后又调用了getProxy获得一个客户端-side 的代理对象。

RpcEngine.getProxy()的实现如下(我们进入的是ProtobufRpcEngine的实现):

1f5d9346cd328551c7b0cf854af84f13.png

进到这里一切豁然开朗,可以看到这里使用了JDK的动态代理。我们关注这句代码:

return new ProtocolProxy(protocol, (T) Proxy.newProxyInstance(
        protocol.getClassLoader(), new Class[]{protocol}, invoker), false);

new ProtocolProxy()的第二个参数代表这个对象里保存的代理对象。

(T) Proxy.newProxyInstance(
        protocol.getClassLoader(), new Class[]{protocol}, invoker)

生成代理对象使用JDK中Proxy类的静态方法newProxyInstance。第三个参数是InvocationHandler的实现,真正的方法调用就在这个InvocationHandler里的invoke里调用。我们看到传入的invoke是new的ProtobufRpcEngine的内部类Invoker。这个Invoker最终会在invoke方法中去调用Client.call方法向RPC Server发送RPC请求,这个过程对客户端是完全透明的。如下图所示, 已用红框标出。

f981bc46ee2002a8c06fc886ec371219.png

至此我们是明白了客户端是如何把RPC请求发送到服务器了。总结一下(采用正序的方式)

  1. 因为我们调用方法一般是使用DFSClient这个类的对象去调用,所以在DFSClient里搜rename方法。可以看到这个方法内部调用namenode.rename()方法。那么我们就需要知道那么namenode是怎么构造出来的。

75600604996dd8718a857831795e251e.png
  1. namenode的声明如下:

final ClientProtocol namenode;

它是一个ClientProtocol类型的变量,因此可以调用所有客户端对NN进行操作的方法。接下来找构造函数,看看如何给namenode成员变量赋值的。

527644342cc061aa138bb98df8e3ae1e.png

DFSClient在自己的构造函数里会调用 NameNodeProxiesClient.createProxyWithClientProtocol()来获得一个支持ClientProtocol协议的代理对象。最后把NameNode的代理赋值给namenode成员。这样我们就可以通过namenode对象来调用各种方法操作了。

  1. 创建这个代理的方法是如下代码:

6b8d588a1913932f01cbc7a5604a415e.png

红色箭头所指分别代表创建non-HA的和HA的代理。如果配置了dfs.client.failover.proxy.provider.$nameservice属性,就认为是开启HA的集群。因为现在集群几乎都是HA的,所以我们看下面这个箭头的创建HA代理对象的方法createHAProxy。记住传入的最后两个参数ClientProtocol.class和failoverProxyProvider。后面我们还会用到这两个参数,到时候可以再回来看。

createHAProxy方法代码如下:

  public static  ProxyAndInfo createHAProxy(
      Configuration conf, URI nameNodeUri, Class xface,
      AbstractNNFailoverProxyProvider failoverProxyProvider) {
    Preconditions.checkNotNull(failoverProxyProvider);// HA case
    DfsClientConf config = new DfsClientConf(conf);//我们主要看这个,因为你看方法的返回值是Proxy和Info,我们只需要关注Proxy就好了。
    T proxy = (T) RetryProxy.create(xface, failoverProxyProvider,
        RetryPolicies.failoverOnNetworkException(
            RetryPolicies.TRY_ONCE_THEN_FAIL, config.getMaxFailoverAttempts(),
            config.getMaxRetryAttempts(), config.getFailoverSleepBaseMillis(),
            config.getFailoverSleepMaxMillis()));
    Text dtService;if (failoverProxyProvider.useLogicalURI()) {
      dtService = HAUtilClient.buildTokenServiceForLogicalUri(nameNodeUri,
          HdfsConstants.HDFS_URI_SCHEME);
    } else {
      dtService = SecurityUtil.buildTokenService(
          DFSUtilClient.getNNAddress(nameNodeUri));
    }return new ProxyAndInfo<>(proxy, dtService,
        DFSUtilClient.getNNAddressCheckLogical(conf, nameNodeUri));
  }

因为一般我们都会有retry机制,所以这里使用了RetryProxy去create代理。跟到RetryProxy.create中。注意create的前两个参数就是刚刚让大家记住的两个。分别是:ClientProtocol.class和failoverProxyProvider。

进到RetryProxy.create源码:

c825d9ba5f3ba607553956c2fb802e3e.png

此时这个泛型T,其实就是ClientProtocol。这个方法里使用JDK的动态代理生成代理对象,这块我们应该很熟悉。newProxyInstance的三个参数,我们看第三个参数,因为在代理对象调用方法最终都会由这个RetryInvocationHandler的invoke方法接管。所以我们去看看RetryInvocationHandler的实现。点进去。

80d9cb69606ff0488213c80a83072945.png

可以看到,RetryInvocationHandler的构造方法中还是有我们之前让大家记住的参数failoverProxyProvider。

因为JDK的动态代理最终方法会走到invoke。所以我们直接去看RetryInvocationHandler的invoke方法。

3c40f5d9c21db5283833a3ac0a9d13a9.png

这里主要是通过循环去实现retry。循环中关键方法是invokeOnce()。点进去。我们关注正常情况下的处理,先不关注异常情况。正常情况下就是再调用invoke()

63789efbca33f779977e0a2e79302ffa.png

再点进去:

14c7871949462004fe24fc6990487e78.png

继续点进invokeMethod()方法中:

874b8b112df6f90f1636df4d6ec5394e.png

再点进invokeMethod中,终于到头了。不能再继续往下点invoke了,那就是JDK的方法了。框起来的代码表示在代理对象上调用此Method底层代表的方法(本例是rename),并把args作为参数传给它。

6aada838f4d20af0638009071ee76c98.png

那这个代理对象是谁呢,proxyDescriptor.getProxy()返回的是什么呢?这时候想想刚才让大家记住的那个参数。

81aff9bb8b04fe3cb6da66f803904447.png

所以proxyDescriptor里面的proxy就是proxyProvider中保存的代理对象信息。而创建这个proxyProvider的时机正是在DFSClient调用的createProxyWithClientProtocol方法里。而且,从下面的的代码可以看到,if (failoverProxyProvider == null)还会再这样我们就可以唱:“又回到最初的起点,呆呆的站在代码前”。

8154c9fe6e18dd83f25e33131e8e1de1.png

点进去看看怎么创建的failoverProxyProvider。经过一系列重载,最终走到下图这个地方。可以看到是通过反射机制,去new的FailoverProxyProvider对象。newInstance的第三个参数xface就是我们的代理类的类型,所以最终这个failoverProxyprovider里面会有我们需要的代理对象。到此分析结束。

644d4d1f3f196bdf46eb5a83de02099b.png

这里面还有一个细节。就是如何得到的FailoverProxyProvider的Class对象。通过跟踪getFailoverProxyProviderClass方法。

e5682da28d71e93dd95588f95be0fb44.png

上图红框中圈出的configKey = “dfs.client.failover.proxy.provider”+host。这个host是在core-site.xml中fs.defaultFS这个属性里配置的,把hdfs的schema去掉就是host。这个配置正好对应了官网hdfs-site.xml中的:

7c2fd615f579eabf10131a39a36b5355.png

那这个host就是nameservice ID。为什么这么说呢,因为官网配置解释就这么说的:

310f0be5c10c5a93bd7550fe772b4915.png

那我们看看一般这个类是什么,可以看到,一般是ConfiguredFailoverProxyProvider这个类。我们通过这个配置项拿到了类的全路径名。

3f034f1ce1e885e0a6999814b32d58c3.png

最后通过Class.forName就加载了这个类。

578c556fe0d9e2a1dd8fcf6aa4336e79.png

大功告成。

  1. 创建完namenode这个代理对象之后,就可以通过它调用各种方法了。比如我们之前举例的rename。我们点进去,进入了ClientProtocol接口。那最终肯定调用的是它的实现类。这就回到了我们文章开头。

至此Hadoop RPC在客户端一侧的调用流程已经全部分析完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556650.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

父子结构查询_Java面试准备(5)之数据结构与算法——红黑树

欢迎点赞评论关注~~~~~~~如上图&#xff0c;二叉查找树极端情况下可能会变成一个单链表&#xff0c;这种查询时间复杂度就变成O(n)了&#xff0c;红黑树在二叉查找树的基础上进行了自平衡。1.原理分析如上图&#xff0c;红黑树具有以下特征&#xff1a;1. 每个节点要么是黑色&a…

中海达数据怎么转rinex_cors账号网最新实战教程,中海达 F61 Plus RTK连接千寻cors账号的方法...

RTK在工程测量工作中越来越流行&#xff0c;在这股潮流中&#xff0c;中海达品牌的F61 Plus因为融合了中海达多年的成熟建站技术HD-CORS&#xff0c;在工程测量工作中也受到了很大欢迎。它可以配套各种cors账号使用&#xff0c;使用过程中只需一台RTK移动站即可进行数据采集、施…

Shiro之UsernamePasswordTokenRememberMeAuthenticationTokenAuthenticationToken

继承关系 先看一下三者的继承关系&#xff0c;会有一个比较清楚的认识 AuthenticationToken AuthenticationToken 用于收集用户提交的身份&#xff08;如用户名&#xff09;及凭据&#xff08;如密码&#xff09;。Shiro会调用CredentialsMatcher对象的doCredentialsMatch方法对…

华为手机滑动速度设置_华为手机打字速度慢?开启这个设置,一分钟就能打200字...

很多朋友都说自己的打字速度非常慢&#xff01;每次使用手机聊天、记录工作事项大半天还没打一段字来。其实使用华为手机就能非常快速的码字&#xff0c;不管聊天还是工作&#xff0c;使用这个方法&#xff0c;一分钟就能打200字。1.聊天快速打字手机键盘因为体积的原因&#x…

SpringBoot 使用AOP功能

RPC&#xff0c;AOP都会用到代理&#xff0c;代理的技术有jdk的Proxy代理(必须实现接口)&#xff0c;cglib(可以不实现接口&#xff0c;直接实现类)&#xff0c;Javassist(jboss )而Spring boot本身也在方方面面使用了代理技术,在Spring中有两种动态代理方式&#xff0c;分别为…

cognos报表导出excel_有了这个报表工具,一键生成自定义的各种报表,还可以导出Excel...

EasyReport是一个简单易用的Web报表工具,它的主要功能是把SQL语句查询出的数据转换成报表页面&#xff0c; 同时支持表格的跨行(RowSpan)与跨列(ColSpan)配置。 同时它还支持报表Excel导出、图表显示及固定表头与左边列的功能。功能介绍本工具从数据库(MySQL,Oracle,SQLServer,…

java自定义注解实现日志功能

一、spring aop的通知类型 1、前置通知&#xff08;Before&#xff09;&#xff1a;在连接点前执行&#xff0c;不会影响连接点的执行&#xff0c;除非抛异常&#xff1b; 2、后置通知&#xff08;AfterReturning&#xff09;&#xff1a;在连接点正常执行完成后执行&#xff0…

java自定义注解annotation记录操作日志

说到注解我们平常用的可以说非常多啦&#xff0c;说几个常用的的注解 RestController Service Autowired 这些都是我们平常使用spring框架最常见的注解了&#xff0c;我们只知道它们非常好用&#xff0c;使用RestController 就能构建一个restful的控制器,Service 这个是我们常用…

数组concat_js 标准二维数组变一维数组的方法

问题&#xff1a;[[1, 1], [2, 3], [4, 5]] -> [1, 1, 2, 3, 4, 5]&#xff1f;方法一利用es5的arr.reduce(callback[, initialValue])实现var arr1 [[0, 1], [2, 3], [4, 5]]; var arr2 arr1.reduce(function (a, b) { return a.concat(b)} ); // arr2 [0, 1, 2, 3, 4, 5…

java 自定义注解+AOP实现日志记录

ssm版本&#xff1a; 1、首先自定义一个注解&#xff0c;该注解有两个属性&#xff0c;一个是模块名&#xff0c;一个是操作的内容。该注解是用来修饰Service层中的方法的。 2、创建一个切面类&#xff0c;该切面使用Aspect和Component注解修饰&#xff0c;该页面需要注入一个…

是人是谁_谁是白鹤滩最可爱的人

白鹤滩水电站是全球在建第一大水电站&#xff0c;主要特性指标均位居世界水电工程前列&#xff0c;2021年7月&#xff0c;首批机组投产发电将是白鹤滩工程为建党一百周年献礼的重大壮举。建设中的白鹤滩水电站工程建设不停步&#xff0c;白鹤滩水电站未来的运行管理者——白鹤滩…

potplayer 多个进程_进程组、会话、控制终端概念,如何创建守护进程?

守护进程概念&#xff1a;守护进程&#xff0c;也就是通常所说的Daemon进程&#xff0c;是Linux中的后台服务进程。周期性的执行某种任务或等待处理某些发生的事件。Linux系统有很多守护进程&#xff0c;大多数服务都是用守护进程实现的。比如&#xff1a;像我们的tftp&#xf…

acs880 用户手册_华中数控、广州数控系统用户手册

数控加工仿真系统 广州数控系统用户手册上海宇龙软件工程有限公司2004 年 5 月华中数控、广州数控系统用户手册 目录I目录第一章 基本操作 ............................................................................................ 1 1.1 项目文件 ...................…

亚马逊出的平板电脑_美国最畅销的安卓平板电脑,还只有2GB内存

在美国除了iPad&#xff0c;谁家的平板电脑卖得最好&#xff1f;不是华为小米&#xff0c;也不是微软或谷歌&#xff0c;而是Amazon亚马逊。主打入门级定位的亚马逊Fire系列平板电脑&#xff0c;在北美的平板市场上&#xff0c;有着举足轻重的地位。今天&#xff0c;亚马逊正式…

对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...

​前言在本文开始之前&#xff0c;作者一直有个疑惑&#xff0c;就是面试题是只写写问题和答案就草草了事&#xff0c;还是应该深入分析一下其背后发生的一些原理。和朋友探讨以后作者还是决定采用后者的方式&#xff0c;因为我认为不仅要做到知其一&#xff0c;更要知其二&…

资源不足的情况怎么设置sparkrdd并行度_监控录像机资源不足或达到上限的原因及解决方法!...

在安装网络监控摄像机过程中&#xff0c;很多人遇到硬盘录像机画面上提升“资源不足”或性能“达到上限”的问题&#xff0c;新手遇到这样的问题会选择重启录像机&#xff0c;但是几次反复发现并不能解决。监控录像机资源不足或达到上限的原因及解决方法&#xff01;首先这种提…

主动变被动9个例句_高中英语 :主动表被动的适用范围

1. 表衡量的动词。The room measures 5 by 6.2. sell, write, wash, read, wear, keep, drink等表状态的情况下。The pen writes well. The clothes wash well.3. 在动词不定式中主语发出的动作。I have a lot of work to do.4. 动词不定式前面的词为形容词时。The question …

为什么要重写hashcode方法和equals方法

为什么要重写hashcode方法和equals方法 我们可能经常听到说重写equals方法必须重写hashcode方法&#xff0c;这是为什么呢&#xff1f;java中所有的类都是Object的子类&#xff0c;直接上object源码 /** Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights …

python代码_python爬虫19 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!

你好由于你是游客无法查看本文请你登录再进谢谢合作当你在爬某些网站的时候需要你登录才可以获取数据咋整&#xff1f;莫慌小帅b把这几招传授给你让你以后从容应对那么接下来就是学习 python 的正确姿势登录的常见方法无非是这两种1、让你输入帐号和密码登录2、让你输入帐号密码…

利用电脑上自带指纹识别嵌入程序中_Win 10 隐藏功能:不用任何软件就可实现手机投屏到电脑...

投屏工具我也介绍了不少&#xff0c;所有的都是需要安装第三方软件的。不过&#xff0c;其实 Windows 10 就自带了手机投影到电脑的功能&#xff0c;不需要任何软件就能实现。在设置中打开系统&#xff0c;找到投影到此电脑&#xff0c;在红框中根据你的需要设置好&#xff0c;…