对hadoop之RPC的理解

因为公司hadoop集群出现了一些瓶颈,在机器不增加的情况下需要进行优化,不管是存储还是处理性能,更合理的利用现有集群的资源,所以来学习了一波hadoop的rpc相关的知识和hdfs方面的知识,以及yarn相关的优化,学完之后确实明白了可以在哪些方面进行优化,可以对哪些参数进行调整,有点恍然大悟的感觉,本文的大部分的内容来于《Hadoop 2.x HDFS源码剖析》,自认为这本书写的挺好,确实能学到很多东西,看了本篇博客如果不懂,还是可以继续学习这本书,讲的很详细,很清晰。本篇文章主要从RPC的原理、hdfs通信协议和Hadoop RPC的实现这三部分进行阐述。

一、RPC原理 1.1、RPC框架

  RPC(Pemote Procedure CallProtocol)是一种通过网络调用远程计算机服务协议,RPC协议假定存在某些网络传输协议,如TCP,UDP,并通过这些传输协议为通信程序之间传递访问请求或者应答信息。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。为实现该目标,RPC 框架需提供一种透明调用机制让使用者不必显式的区分本地调用和远程调用。

  RPC通常采用客户机/服务器模型。请求程序是一个客户机,而服务提供程序则是一个服务器。客户端首先会发送一个有参数的调用请求到服务端,等待服务端的响应消息,在服务端,服务提供程序会保持睡眠状态直到有调用请求到达为止,当接收到请求,服务端会对请求就行调用,计算结果,最后返回给客户端。RPC的框架图如下图所示:

对hadoop之RPC的理解

  上图所示,RPC主要包括如下几个部分:

1、通信模块:传输RPC请求和响应的网络通信模块,可以基于TCP协议,也可以基于UDP协议,它们在客户和服务器之间传递请求和应答消息,一般不会对数据包进行任何处理。请求–应答协议的实现方式有同步方式和异步方式两种,如下图所示。

对hadoop之RPC的理解

2、客户端的stub程序:在客户端stub程序表现为像本地程序一样,但底层会将调用参数和请求序列化并通过通信模块发送给服务器。之后stub会等待服务器的响应信息,并将响应信息反序列化给请求程序。
3、服务端stub程序:stub程序会将客户端发送的调用请求和参数反序列化,根据调用信息触发对应的服务程序,然后将服务程序的响应信息徐丽华并发回给客户端。
4、请求程序:请求程序像本地调用方法一样调用客户端stub程序,然后接收stub程序的返回响应信息。
5、服务程序:服务端会接收来自stub的调用请求,执行对应的逻辑并返回执行结果。

1.2、RPC特点

透明性:远程调用其他机器上的程序,对用户来说就像调用本地方法一样。

高性能:RPC Server能够并发处理多个来自Client的请求。

可控性:JDK中已经提供了一个RPC框架——RMI,但是该PRC框架过于重量级并且可控之处比较少,所以Hadoop RPC实现了自定义的RPC框架。

1.3、RPC请求基本步骤

客户程序以本地方式调用系统产生的客户端的Stub程序;

该Stub程序将函数调用信息序列化并按照网络通信模块的要求封装成消息包,并交给通信模块发送到远程服务器端。

远程服务器端接收此消息后,将此消息发送给相应的服务端的Stub程序;

Stub程序拆封消息,并反序列化,形成被调过程要求的形式,并调用对应函数;

被调用函数按照所获参数执行,并将结果返回给服务端的Stub程序;

Stub程序将此结果封装成消息,通过网络通信模块逐级地传送给客户程序。

二、HDFS的通信协议

HDFS通信协议抽象了HDFS各个节点之间的调用接口,主要分为hadoop RPC接口和流式接口

2.1、hadoop RPC接口

1、ClientProtoclo

  该接口定义客户端与namenode节点间的接口,用于客户端对文件系统的所有操作,读写都需要与该接口交互。
  该接口定义了由客户端发起,namenode响应的操作,主要包括hdfs文件读写的相关操作,hdfs命名空间,快照,缓存相关的操作。
  (客户端与Namenode交互)一般性操作,客户端会通过getBlockLocations()方法向Namenode获取文件的具体位置信息(指的是存储这个数据块副本的所有datanode的信息),还会使用reportBadBlocks()方式向Namenode汇报错误的数据块。
  (写,追写数据)首先会使用create()方法通过hdfs文件系统目录树中创建一个新的空文件,然后调用addBlock()方法获取存储文件的数据块的位置信息,最后客户端根据位置信息与datanode建立数据流管道,写入数据。追写略有不同,首先通过append()方法获取最后一个可写数据块的位置信息并打开一个已有的文件(没有写满的),然后建立好数据管道流,并向节点中追写数据,当写满后,则会像create()方法一样,客户端会调用addBlock()方法获取新的数据块。当客户端完成了整个文件的写入操作后,会调用complete()方法通知Namenode,这个操作会提交新写入的HDFS文件的所有数据块,当数据块满则副本数时,则返回true,否则返回false;会重试。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzpff.html