Hadoop学习<四>--HDFS的RPC通信原理总结

这里先写下自己学习RPC的笔记总结,下面将详细介绍学习过程:

RPC(remote procedure call)

不同java进程间的对象方法的调用。

一方称作服务端(server),一方称作客户端(client)。

server端提供对象,供客户端调用的,被调用的对象的方法的执行发生在server端。

RPC是hadoop框架运行的基础。

通过rpc小例子获得的认识?

1. 服务端提供的对象必须是一个接口,接口extends VersioinedProtocal

2. 客户端能够的对象中的方法必须位于对象的接口中。

查看一个基类或者接口的派生类或实现类---鼠标指向类名,Ctrl + T  ;

查看函数的调用关系(找到所有调用该方法的函数)--Ctrl + Alt + H (ubuntu系统快捷键占用,可以类名右键找open call Hierarchy,结果在控制台输出) ;

快速查找类对象的相关信息 -- Ctrl + O(查找类名的所有成员变量和方法),F3查看类名的定义。

RPC 是远程过程调用(Remote Procedure Call),即远程调用其他虚拟机中运行的 java object。RPC 是一种客户端/服务器模式,那么在使用时包括服务端代码和客户端代码,还有我们调用的远程过程对象。

HDFS 的运行就是建立在此基础之上的。这里通过分析实现一个简单的 RPC 程序来分析HDFS 的运行机理。

1.首先定义远程调用类的接口,接口继承的 VersionedProtocal,是hadoop 的 RPC 的接口,所有的 RPC 通信必须实现这个一接口,用于保证客户端和服务端的端口一致。服务端被调用的类必须继承这个接口 VersionedProtocal。

package com.RPC;

import org.apache.hadoop.ipc.VersionedProtocol;
public interface MyBizable extends VersionedProtocol{
    //定义抽象类方法hello
	public abstract String hello(String name);
}

2.然后编写远程调用类,实现这个接口MyBizable,这里面有两个方法被实现,一个就是 hello方法,另一个是 getProtocalVersion 方法。

package com.RPC;

import java.io.IOException;
//实现接口MyBizable,重写hello和getProtocolVersion方法
public class MyBiz implements MyBizable{
	public static long BIZ_VERSION = 123456L;
	@Override
	public String hello(String name) {
		System.out.println("我是ByBiz,我被调用了。");
		return "hello" + name;
	}

	@Override
	public long getProtocolVersion(String protocol, long clientVersion)
			throws IOException {
		//<span style="color:#FF0000;">返回BIZ_VERSION,保证服务器和客户端请求版本一致</span>
		return BIZ_VERSION;
	}
}

3.有了远程调用对象,我们就可以编写服务器端代码,详细在代码中有介绍。

package com.RPC;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;

public class MyServer {
	//定义final类型服务器地址和端口
	public static final String SERVER_ADDRESS = "localhost";
	public static final int SERVER_PORT = 1234;
	/**
	 * RPC是远程过程调用(Remote Procedure Call)
	 */
	public static void main(String[] args) throws Exception {
		Configuration conf = new Configuration();
		//重点RPC.getServer方法,该方法有四个参数,第一个参数是被调用的 java对象,
		//第二个参数是服务器的地址,第三个参数是服务器的端口。获得服务器对象后,
		//启动服务器。这样,服务器就在指定端口监听客户端的请求。
		final Server server = RPC.getServer(new MyBiz(), SERVER_ADDRESS, SERVER_PORT, conf);
		server.start();
	}
}

4.最后,我们就可以编写客户端代码,来调用服务器方法,注意方法在服务器实现。

package com.RPC;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;

public class MyClient {
	/**
	 * RPC客户端
	 */
	public static void main(String[] args) throws Exception {
		//RPC.getProxy(),该方法有四个参数,第一个参数是被调用的接口类,
		//第二个是客户端版本号,第三个是服务端地址。返回的代理对象,
		//就是服务端对象的代理,内部就是使用 java.lang.Proxy 实现的。
		final MyBizable proxy = (MyBizable) RPC.getProxy(MyBizable.class,
				MyBiz.BIZ_VERSION, new InetSocketAddress(MyServer.SERVER_ADDRESS, MyServer.SERVER_PORT) ,new Configuration() );
		//调用接口中的方法
		final String result = proxy.hello("world");
		//打印返回结果,然后关闭网络连接
		System.out.println(result);
		RPC.stopProxy(proxy);
	}
}

注意上面RPC获取代理方法中接口是调用对象的接口对象,由此可以得出在客户端调用的业务类的方法是定义在业务类的接口中的。该接口实现了 VersionedProtocal 接口。

完成了上面的操作,我们先启动服务端,再启动客户端。观察服务端和客户端输出信息。然后,我们在命令行输入之前查看hadoop节点运行情况的命令jps,输出如下图:

我们可以看到一个 java 进程,是“MyServer”,该进程正是我们刚刚运行的 rpc 的服务端类MyServer。那么可以判断,hadoop 启动时产生的 5 个 java 进程也应该是RPC 的服务端。我们观察 NameNode 的源代码,可以看到 NameNode 确实创建了RPC 的服务端(在namenode类的初始化Initialize方法中,为方便观察,我复制源码,重点查看create server部分)。

 /**
   * Initialize name-node.
   *
   * @param conf the configuration
   */
  private void initialize(Configuration conf) throws IOException {
    InetSocketAddress socAddr = NameNode.getAddress(conf);
    UserGroupInformation.setConfiguration(conf);
    SecurityUtil.login(conf, DFSConfigKeys.DFS_NAMENODE_KEYTAB_FILE_KEY,
        DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY, socAddr.getHostName());
    int handlerCount = conf.getInt("dfs.namenode.handler.count", 10);

    // set service-level authorization security policy
    if (serviceAuthEnabled =
          conf.getBoolean(
            ServiceAuthorizationManager.SERVICE_AUTHORIZATION_CONFIG, false)) {
      PolicyProvider policyProvider =
          (PolicyProvider)(ReflectionUtils.newInstance(
              conf.getClass(PolicyProvider.POLICY_PROVIDER_CONFIG,
                  HDFSPolicyProvider.class, PolicyProvider.class),
              conf));
        ServiceAuthorizationManager.refresh(conf, policyProvider);
    }

    myMetrics = NameNodeInstrumentation.create(conf);
    this.namesystem = new FSNamesystem(this, conf);

    if (UserGroupInformation.isSecurityEnabled()) {
      namesystem.activateSecretManager();
    }

    <span style="color:#FF0000;">// create rpc server</span>
    InetSocketAddress dnSocketAddr = getServiceRpcServerAddress(conf);
    if (dnSocketAddr != null) {
      int serviceHandlerCount =
        conf.getInt(DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_KEY,
                    DFSConfigKeys.DFS_NAMENODE_SERVICE_HANDLER_COUNT_DEFAULT);
      this.serviceRpcServer = <span style="color:#FF0000;">RPC.getServer(this, dnSocketAddr.getHostName(),
          dnSocketAddr.getPort(), serviceHandlerCount,
          false, conf, namesystem.getDelegationTokenSecretManager());</span>
      this.serviceRPCAddress = this.serviceRpcServer.getListenerAddress();
      setRpcServiceServerAddress(conf);
    }
    this.server = RPC.getServer(this, socAddr.getHostName(),
        socAddr.getPort(), handlerCount, false, conf, namesystem
        .getDelegationTokenSecretManager());

    // The rpc-server port can be ephemeral... ensure we have the correct info
    this.serverAddress = this.server.getListenerAddress();
    FileSystem.setDefaultUri(conf, getUri(serverAddress));
    LOG.info("Namenode up at: " + this.serverAddress);

    startHttpServer(conf);
    this.server.start();  //start RPC server
    if (serviceRpcServer != null) {
      serviceRpcServer.start();
    }
    startTrashEmptier(conf);
  }

由上可以看到 NameNode 本身就是一个 java 进程。观察图 5-2 中 RPC.getServer()方法的第一个参数,发现是 this,说明 NameNode 本身就是一个位于服务端的被调用对象,即 NameNode 中的方法是可以被客户端代码调用的。根据 RPC 运行原理可知,NameNode暴露给客户端的方法是位于接口中的。

继续查看namenode类的接口实现,可以看到 NameNode 实现了 ClientProtocal、DatanodeProtocal、NamenodeProtocal 等接口。

下面在接着分析namenode实现的这些常用接口作用,由谁调用实现:

ClientProtocal 由DFSclient调用

这个接口是供客户端调用的。这里的客户端不是指的我们自己写的代码,而是hadoop 的一个类叫做 DFSClient。在 DFSClient 中会调用 ClientProtocal 中的方法,完成一些操作。

该接口中的方法大部分是对 HDFS 的操作,如 create、delete、mkdirs、rename 等。

DatanodeProtocal 由DataNode调用

这个接口是供 DataNode 调用的。 DataNode 调用该接口中的方法向 NameNode 报告本节点的状态和 block 信息。

NameNode 不 能 向 DataNode 发 送 消 息 , 只 能 通 过 该 接 口 中 方 法 的 返 回 值 向DataNode 传递消息。

NamenodeProtocal 由SecondaryNameNode 调用

这个接口是供 SecondaryNameNode 调用的。SecondaryNameNode 是专门做NameNode 中 edits 文件向 fsimage 合并数据的。

对于datanode节点的接口实现,分析思路大体一致,就是根据具体接口,查看接口协议功能,这是查看hadoop源码的学习经验,常用的一些myeclipse快捷键如下:

查看一个基类或者接口的派生类或实现类---鼠标指向类名,Ctrl + T  ;

查看函数的调用关系(找到所有调用该方法的函数)--Ctrl + Alt + H (ubuntu系统快捷键占用,可以类名右键找open call Hierarchy,结果在控制台输出) ;

快速查找类对象的相关信息 -- Ctrl + O(查找类名的所有成员变量和方法),F3查看类名的定义;

具体快捷键可以通过鼠标类名,右键查看所有可用方法。

那对于datanode的接口大家可以通过上面快捷键练习下,也分析下接口功能,学习datanode重要两个接口,分别是 InterDatanodeProtocal、ClientDatanodeProtocal。今天就总结到这里。

时间: 2024-08-14 22:06:54

Hadoop学习<四>--HDFS的RPC通信原理总结的相关文章

hadoop 学习之hdfs shell命令

1.HDFS shell 1.0查看帮助  hadoop fs -help <cmd> 1.1上传  hadoop fs -put <linux上文件> <hdfs上的路径> 1.2查看文件内容  hadoop fs -cat <hdfs上的路径> 1.3查看文件列表  hadoop fs -ls / 1.4下载文件  hadoop fs -get <hdfs上的路径> <linux上文件>

hadoop学习之HDFS

1.什么是大数据?什么是云计算?什么是hadoop? 大数据现在很火,到底什么是大数据,多大的数据才算大,一般而言对于TB级以上的数据我们成为大数据,对于这些数据它的价值在哪?大数据的价值就是我们大量的数据中分析出有价值的信息,来判断一些行为等等信息.而这些大数据存储在哪?如何进行分析?这就衍生了Hadoop. 云计算是什么?通俗的说云计算就是大规模的计算机集群(即多台服务器集群),我们通过软件将这些计算机整合起来,根据需求根据用户来提供服务.比如进行一些数据的计算分析.用来提高工作效率.(这是

Hadoop源码解析之 rpc通信 client到server通信

rpc是Hadoop分布式底层通信的基础,无论是client和namenode,namenode和datanode,以及yarn新框架之间的通信模式等等都是采用的rpc方式. 下面我们来概要分析一下Hadoop2的rpc. Hadoop通信模式主要是C/S方式,及客户端和服务端的模式. 客户端采用传统的socket通信方式向服务端发送信息,并等待服务端的返回. 服务端采用reactor的模式(Java nio)的方式来处理客户端的请求并给予响应. 一.客户端到服务端的通信 下面我们先分析客户端到

Hadoop 学习之——HDFS

HDFS是HADOOP中的核心技术之一——分布式文件存储系统.Hadoop的作者Doug Cutting 和Mike 是根据Google发布关于GFS 的研究报告所设计出的分布式文件存储系统. 一.HDFS设计的前提或者假设有6个: 硬件错误是常态而不是异常.对于普通的每台机器来说,出现故障可能并是是常事,但HDFS可能由成千上万的机器组成,在这中情况下发生硬件错误就变成非常正常的事情.为了能够正常的工作,HDFS要能处理或者容忍这些硬件错误.所以对HDFS 来说硬件错误是常态而不是错误. 流式

hadoop学习笔记-HDFS的REST接口

在学习HDFS的过程中,重点关注了HDFS的REST访问接口.以前对REST的认识非常笼统,这次通过对HDFS的REST接口进行实际操作,形成很直观的认识. 1? 写文件操作 写文件操作分为两个命令,第一个命令先产生一个重定向(TEMPORARY_REDIRECT)响应报文,响应报文中的Location字段即为重定向的目标地址,这个目标地址指向的就是分配的datanode,用以存储后面写入的内容.第二个命令的URL写的就是第一个命令重定向的目标地址.(注意:在路径前面需要加"/webhdfs/v

hadoop学习记录--hdfs文件上传过程源码解析

本节并不大算为大家讲接什么是hadoop,或者hadoop的基础知识因为这些知识在网上有很多详细的介绍,在这里想说的是关于hdfs的相关内容.或许大家都知道hdfs是hadoop底层存储模块,专门用于存放数据,那么在进行文件上传的时候hdfs是如何进行的呢?我们按照宏观和微观来进行相关解析工作. 首先需要向大家解释如下几个概念: (1) secondaryNamenode: 其实起初我对SN的理解也和大部分人相同,认为SN是NN(nameNode)的一个实时热备份实现HA,并且在一次笔试的过程中

【Hadoop学习】HDFS中的集中化缓存管理

Hadoop版本:2.6.0 本文系从官方文档翻译而来,转载请尊重译者的工作,注明以下链接: http://www.cnblogs.com/zhangningbo/p/4146398.html 概述 HDFS中的集中化缓存管理是一个明确的缓存机制,它允许用户指定要缓存的HDFS路径.NameNode会和保存着所需快数据的所有DataNode通信,并指导他们把块数据缓存在off-heap缓存中. HDFS集中化缓存管理具有许多重大优势: 1.明确的锁定可以阻止频繁使用的数据被从内存中清除.当工作集

【Hadoop学习】HDFS 短路本地读

Hadoop版本:2.6.0 本文系从官方文档翻译而来,转载请尊重译者的工作,注明以下链接: http://www.cnblogs.com/zhangningbo/p/4146296.html 背景 在HDFS中,通常是通过DataNode来读取数据的.但是,当客户端向DataNode请求读取文件时,DataNode就会从磁盘读取该文件并通过TCP socket将数据发送到客户端.所谓“短路”是指旁路DataNode来读取文件,也就是说,允许客户端直接读取文件.很明显,这种情况只在客户端与数据放

RPC通信原理

什么是 RPCRPC(Remote Procedure Call Protocol)远程过程调用协议.通俗的描述是:客户端在不知道调用细节的情况下,调用存在于远程计算上的某个过程或函数,就像调用本地应用程序中的一样. 正式的描述是:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. RPC 主要特质: RPC 是协议:协议意味着规范.目前典型的 RPC 实现包括Hetty 等.但这些实现往往都会附加其他重要功能,例如 Du理.访问权限管理等功能. 网络协议和网络 IO 模型