尽管这里是hadoop的rpc服务,但是hadoop还是做到了一次连接仅有一次认证。具体的流程待我慢慢道来。
  客户端:这里我们假设ConnectionId对应的Connection并不存在。在调用getConnection方法时,这里构造了Connection,由于入参ConnectionId.doPing一般为true,因此,在Connection的构造方法时,会构造相应的pingHeader写入到成员变量pingRequest中。接着将call加入到connection中后,调用了connection.setupIOstreams,这里一开始就调用了writeConnectionHeader,一共写了7个字节的内容到服务端(分别是"hrpc",Version、Service Class、AuthProtocol,显然,前面是四个字节,后面三个都是一个字节)。另外,由于这里的成员变量doPing为true,因此,这里使用PingInputStream封装了上面获取的输入流。该方法内接着调用了writeConnectionContext,该方法就是rpc的认证调用。这里的callId设置为CONNECTION_CONTEXT_CALL_ID,这里最后调用了request.write,将request中的信息写到了out中,注意,这里并没有调用其flush方法。但是,这里封装了一次请求。接着,调用了connection.sendRpcRequest,这里将请求的call继续写入到out中,并调用了flush方法。至此,客户端的流程也就完成了。
  服务端:关于服务端的流程,我从Server.Listener.run讲起。这里一开始是阻塞的。当客户端调用了flush之后,这里的阻塞被打断。这里然后调用到了doAccept方法。在该方法中首先调用到了ConnectionManager.register,这里新构造了Connection并且将其加入到成员结合connections中。在Connection的构造中封装了客户端的channel、socket等相关信息。然后将新构造的connection作为attachment绑定到SelectionKey上,然后调用reader.addConnection将其加入到阻塞队列pendingConnections,并调用wakeup唤醒了reader在doRunLoop方法中的readSelector.select阻塞。而Server.Listener中的方法继续阻塞。
  接下来,我们重点关注Server.Listener.Reader.doRunLoop。这里的readSelector.select阻塞打断后,由于此时的readSelector中并没有相关的selectedKeys,因此继续循环执行。接着从pendingConnections队列中取出封装了客户端相关信息的Connection,然后将Connection.channel注册到readSelector选择器上,由于客户端已经将信息flush过来,所以,这里的注册后的readSelector不会阻塞,且其中含有相应的selectedKeys,故,接下来会调用到doRead方法,接着调用到了Connection.readAndProcess。接下来另起一段着重讲解。
这里dataLengthBuffer.remaining()>0判断成立,调用channelRead将客户端的版本信息读入。接着将Version、Service Class、AuthProtocol读入到connectionHeaderBuf中,然后调用了dataLengthBuffer.flip,方便下次读取数据长度,并且将connectionHeaderRead置为true,也就是下一次遍历的时候不会再读取头部的相关信息。只是读取实际数据长度。然后,由于data == null,因此,这里为data分配空间,然后调用了processOneRpc,由于这里是封装的CONNECTION_CONTEXT_CALL_ID的call,因此,这里来到processRpcOutOfBandRequest方法,该方法完成了认证的相关流程。由于一开始connectionContextRead为false,而在processRpcOutOfBandRequest方法中被置为true,因此,这里会调用continue。这里重新读取的数据的长度,然后继续调用了processOneRpc。这一次callId不小于0,因此会调用到方法processRpcRequest。该方法是完成真正请求的,也就是说,前面的几次调用只是前期的校验。所谓真正的请求,也就是要调用服务端的相关方法。processRpcRequest方法将客户端的相关信息封装到Call,并将其加入到callQueue中。
  另一方面,在Handler.run中一直在等待callQueue中成员的加入。通过其take方法可以看到内部的阻塞队列一直在轮询等待成员的加入。这里接着调用了CurCall.set(call),方便后面获取客户端的ugi。接着就调用到了RPC.Server.call,由于这里的Server继承自org.apache.hadoop.ipc.Server(该类是一个抽象类),而前面的Server覆写了后面Server的抽象方法call。最终调用了ProtobufRpcEngine.cal,该方法完成了服务端对应方法的调用,并且将结果返回。
  另外,如果客户端在请求超时之后,会调用sendPing方法,用于测试服务端的服务是否仍然开启,此时的callId为PING_CALL_ID。

  至此,hdfs中客户端与服务端的交互就比较详细的展现给大家了。

hadoop rpc协议客户端与服务端的交互流程的更多相关文章

  1. Hadoop RPC源码阅读-服务端Server

    Hadoop版本Hadoop2.6 RPC主要分为3个部分:(1)交互协议 (2)客户端(3)服务端 (3)服务端 RPC服务端的实例代码: public class Starter { public ...

  2. 二、网络编程-socket之TCP协议开发客户端和服务端通信

    知识点:之前讲的udp协议传输数据是不安全的,不可靠不稳定的,tcp协议传输数据安全可靠,因为它们的通讯机制是不一样的.udp是用户数据报传输,也就是直接丢一个数据包给另外一个程序,就好比寄信给别人, ...

  3. Fresco 源码分析(二) Fresco客户端与服务端交互(3) 前后台打通

    4.2.1.2.4 PipelineDraweeControllerBuilder.obtainController()源码分析 续 上节中我们提到两个核心的步骤 obtainDataSourceSu ...

  4. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  5. RPC学习--C#使用Thrift简介,C#客户端和Java服务端相互交互

    本文主要介绍两部分内容: C#中使用Thrift简介 用Java创建一个服务端,用C#创建一个客户端通过thrift与其交互. 用纯C#实现Client和Server C#服务端,Java客户端 其中 ...

  6. 使用Thrift RPC编写程序(服务端和客户端)

    1. Thrift类介绍 Thrift代码包(位于thrift-0.6.1/lib/cpp/src)有以下几个目录: concurrency:并发和时钟管理方面的库processor:Processo ...

  7. java网络编程客户端与服务端原理以及用URL解析HTTP协议

    常见客户端与服务端 客户端: 浏览器:IE 服务端: 服务器:web服务器(Tomcat),存储服务器,数据库服务器. (注:会用到Tomact服务器,在webapps下有一个自己创建的目录myweb ...

  8. 网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例

    UDP协议 (了解) 称之为数据包协议,又称不可靠协议. 特点: 1) 不需要建立链接. 2) 不需要知道对方是否收到. 3) 数据不安全 4) 传输速度快 5)能支持并发 6) 不会粘包 7) 无需 ...

  9. java 从零开始手写 RPC (03) 如何实现客户端调用服务端?

    说明 java 从零开始手写 RPC (01) 基于 socket 实现 java 从零开始手写 RPC (02)-netty4 实现客户端和服务端 写完了客户端和服务端,那么如何实现客户端和服务端的 ...

随机推荐

  1. tkinter中checkbutton多选框控件和variable用法(六)

    checkbutton控件 简单的实现多选: import tkinter wuya = tkinter.Tk() wuya.title("wuya") wuya.geometry ...

  2. 你不知道的JavaScript--Item28 垃圾回收机制与内存管理

    1.垃圾回收机制-GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存. 原理:垃圾收集器会定期(周期性 ...

  3. 在MFC中通过访问IP地址下载文件到本地

    void CDownLoad::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码 CDialogEx::OnOK(); UpdateData(TRUE); CStri ...

  4. BZOJ_1257_ [CQOI2007]余数之和sum_数学

    BZOJ_1257_ [CQOI2007]余数之和sum_数学 题意:给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值. 分 ...

  5. ios swift版 sqlite3详解

    iOS中的SQLite3的封装与详细应用 SQLite是一个开源的嵌入式关系数据库,特点是易使用.高效.安全可靠.可移植性强. iOS中的本地持久化存储 NSUserDefault:一般用于存储小规模 ...

  6. java中的单例模式与静态类

    单例模式与静态类(一个类,所有方法为静态方法)是另一个非常有趣的问题,在<Java中有关单例模式的面试问题>博文中露掉了,由于单例模式和静态类都具有良好的访问性,它们之间有许多相似之处,例 ...

  7. python+appium 【已解决】真机运行appium报错“WebDriverException: Message: A new session could not be created. (Original error: Command failed: C:\Windows\system32\cmd.exe /s /c.......详见内文

    问题报错提示: selenium.common.exceptions.WebDriverException: Message: A new session could not be created. ...

  8. appium--xpath定位元素用法

    一.xpath的使用场景: 自动化测试中经常对元素进行操作时,如果存在id.name.content_desc时,可通过appium框架提供的方法find_element_by_id/name/tag ...

  9. 发现了一个非常棒的pyqt5的例子集

    发现了一个非常棒的pyqt5的例子集 https://github.com/892768447/PyQt 各种各样的PyQt测试和例子 [Python3.4.4 or Python3.5][PyQt5 ...

  10. 从壹开始 [ Id4 ] 之二║ 基础知识集合 & 项目搭建一

    前言 哈喽大家又见面啦,感觉好久没更新了,这几天看了一本书<解忧杂货铺>,嗯挺好的,推荐一下