1.概述

  之前在《Hadoop2源码分析-RPC探索实战》一文当中介绍了Hadoop的RPC机制,今天给大家分享关于YARN的RPC的机制。下面是今天的分享目录:

  • YARN的RPC介绍
  • YARN的RPC示例
  • 截图预览

  下面开始今天的内容分享。

2.YARN的RPC介绍

  我们知道在Hadoop的RPC当中,其主要由RPC,Client及Server这三个大类组成,分别实现对外提供编程接口、客户端实现及服务端实现。如下图所示:

  图中是Hadoop的RPC的一个类的关系图,大家可以到《Hadoop2源码分析-RPC探索实战》一文中,通过代码示例去理解他们之间的关系,这里就不多做赘述了。接下来,我们去看Yarn的RPC。

  Yarn对外提供的是YarnRPC这个类,这是一个抽象类,通过阅读YarnRPC的源码可以知道,实际的实现由参数yarn.ipc.rpc.class设定,默认情况下,其值为:org.apache.hadoop.yarn.ipc.HadoopYarnProtoRPC,部分代码如下:

  • YarnRPC:
public abstract class YarnRPC {
// ...... public static YarnRPC create(Configuration conf) {
LOG.debug("Creating YarnRPC for " +
conf.get(YarnConfiguration.IPC_RPC_IMPL));
String clazzName = conf.get(YarnConfiguration.IPC_RPC_IMPL);
if (clazzName == null) {
clazzName = YarnConfiguration.DEFAULT_IPC_RPC_IMPL;
}
try {
return (YarnRPC) Class.forName(clazzName).newInstance();
} catch (Exception e) {
throw new YarnRuntimeException(e);
}
} }
  • YarnConfiguration类:
public class YarnConfiguration extends Configuration {

  //Configurations
public static final String YARN_PREFIX = "yarn."; ////////////////////////////////
// IPC Configs
////////////////////////////////
public static final String IPC_PREFIX = YARN_PREFIX + "ipc.";
/** RPC class implementation*/
public static final String IPC_RPC_IMPL =
IPC_PREFIX + "rpc.class";
public static final String DEFAULT_IPC_RPC_IMPL =
"org.apache.hadoop.yarn.ipc.HadoopYarnProtoRPC";
}

  而HadoopYarnProtoRPC 通过 RPC 的 RpcFactoryProvider 生成客户端工厂(由参数 yarn.ipc.client.factory.class 指定,默认值是 org.apache.hadoop.yarn.factories.impl.pb.RpcClientFactoryPBImpl)和服务器工厂 (由参数 yarn.ipc.server.factory.class 指定,默认值是 org.apache.hadoop.yarn.factories.impl.pb.RpcServerFactoryPBImpl),以根据通信协议的 Protocol Buffers 定义生成客户端对象和服务器对象。相关类的部分代码如下:

  • HadoopYarnProtoRPC
public class HadoopYarnProtoRPC extends YarnRPC {

  private static final Log LOG = LogFactory.getLog(HadoopYarnProtoRPC.class);

  @Override
public Object getProxy(Class protocol, InetSocketAddress addr,
Configuration conf) {
LOG.debug("Creating a HadoopYarnProtoRpc proxy for protocol " + protocol);
return RpcFactoryProvider.getClientFactory(conf).getClient(protocol, 1,
addr, conf);
} @Override
public void stopProxy(Object proxy, Configuration conf) {
RpcFactoryProvider.getClientFactory(conf).stopClient(proxy);
} @Override
public Server getServer(Class protocol, Object instance,
InetSocketAddress addr, Configuration conf,
SecretManager<? extends TokenIdentifier> secretManager,
int numHandlers, String portRangeConfig) {
LOG.debug("Creating a HadoopYarnProtoRpc server for protocol " + protocol +
" with " + numHandlers + " handlers"); return RpcFactoryProvider.getServerFactory(conf).getServer(protocol,
instance, addr, conf, secretManager, numHandlers, portRangeConfig); } }
  • RpcFactoryProvider

public class RpcFactoryProvider {

  // ......

  public static RpcClientFactory getClientFactory(Configuration conf) {
String clientFactoryClassName = conf.get(
YarnConfiguration.IPC_CLIENT_FACTORY_CLASS,
YarnConfiguration.DEFAULT_IPC_CLIENT_FACTORY_CLASS);
return (RpcClientFactory) getFactoryClassInstance(clientFactoryClassName);
} //...... }
/** Factory to create client IPC classes.*/
public static final String IPC_CLIENT_FACTORY_CLASS =
IPC_PREFIX + "client.factory.class";
public static final String DEFAULT_IPC_CLIENT_FACTORY_CLASS =
"org.apache.hadoop.yarn.factories.impl.pb.RpcClientFactoryPBImpl";

  在 YARN 中并未使用Hadoop自带的Writable来做序列化,而是使用 Protocol Buffers 作为默认的序列化机制,这带来的好处主要有以下几点:

  • 继承Protocol Buffers的优点:Protocol Buffers已被实践证明其拥有高效性、可扩展性、紧凑性以及跨语言性等特点。
  • 支持在线升级回滚:在Hadoop 2.x版本后,添加的HA方案,该方案能够进行主备切换,在不停止NNA节点服务的前提下,能够在线升级版本。

3.YARN的RPC示例

  YARN 的工作流程是先定义通信协议接口ResourceTracker,它包含2个函数,具体代码如下所示:

  • ResourceTracker:
public interface ResourceTracker {

  @Idempotent
public RegisterNodeManagerResponse registerNodeManager(
RegisterNodeManagerRequest request) throws YarnException,
IOException; @AtMostOnce
public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request)
throws YarnException, IOException; }

  这里ResourceTracker提供了Protocol Buffers定义和Java实现,其中设计的Protocol Buffers文件有:ResourceTracker.proto、yarn_server_common_service_protos.proto和yarn_server_common_protos.proto,文件路径在Hadoop的源码包的 hadoop-2.6.0-src/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-common/src/main/proto,这里就不贴出3个文件的具体代码类,大家可以到该目录去阅读这部分代码。这里需要注意的是,若是大家要编译这些文件需要安装 ProtoBuf 的编译环境,环境安装较为简单,这里给大家简要说明下。

  首先是下载ProtoBuf的安装包,然后解压,进入到解压目录,编译安装。命令如下:

./configure --prefix=/home/work /protobuf/  

make && make install

最后编译 .proto 文件的命令:

protoc ./ResourceTracker.proto  --java_out=./

  下面,我们去收取Hadoop源码到本地工程,运行调试相关代码。

  • TestYarnServerApiClasses:

public class TestYarnServerApiClasses {

  // ......

  // 列举测试4个方法  

@Test
public void testRegisterNodeManagerResponsePBImpl() {
RegisterNodeManagerResponsePBImpl original =
new RegisterNodeManagerResponsePBImpl();
original.setContainerTokenMasterKey(getMasterKey());
original.setNMTokenMasterKey(getMasterKey());
original.setNodeAction(NodeAction.NORMAL);
original.setDiagnosticsMessage("testDiagnosticMessage"); RegisterNodeManagerResponsePBImpl copy =
new RegisterNodeManagerResponsePBImpl(
original.getProto());
assertEquals(1, copy.getContainerTokenMasterKey().getKeyId());
assertEquals(1, copy.getNMTokenMasterKey().getKeyId());
assertEquals(NodeAction.NORMAL, copy.getNodeAction());
assertEquals("testDiagnosticMessage", copy.getDiagnosticsMessage()); } @Test
public void testNodeHeartbeatRequestPBImpl() {
NodeHeartbeatRequestPBImpl original = new NodeHeartbeatRequestPBImpl();
original.setLastKnownContainerTokenMasterKey(getMasterKey());
original.setLastKnownNMTokenMasterKey(getMasterKey());
original.setNodeStatus(getNodeStatus());
NodeHeartbeatRequestPBImpl copy = new NodeHeartbeatRequestPBImpl(
original.getProto());
assertEquals(1, copy.getLastKnownContainerTokenMasterKey().getKeyId());
assertEquals(1, copy.getLastKnownNMTokenMasterKey().getKeyId());
assertEquals("localhost", copy.getNodeStatus().getNodeId().getHost());
} @Test
public void testNodeHeartbeatResponsePBImpl() {
NodeHeartbeatResponsePBImpl original = new NodeHeartbeatResponsePBImpl(); original.setDiagnosticsMessage("testDiagnosticMessage");
original.setContainerTokenMasterKey(getMasterKey());
original.setNMTokenMasterKey(getMasterKey());
original.setNextHeartBeatInterval(1000);
original.setNodeAction(NodeAction.NORMAL);
original.setResponseId(100); NodeHeartbeatResponsePBImpl copy = new NodeHeartbeatResponsePBImpl(
original.getProto());
assertEquals(100, copy.getResponseId());
assertEquals(NodeAction.NORMAL, copy.getNodeAction());
assertEquals(1000, copy.getNextHeartBeatInterval());
assertEquals(1, copy.getContainerTokenMasterKey().getKeyId());
assertEquals(1, copy.getNMTokenMasterKey().getKeyId());
assertEquals("testDiagnosticMessage", copy.getDiagnosticsMessage());
} @Test
public void testRegisterNodeManagerRequestPBImpl() {
RegisterNodeManagerRequestPBImpl original = new RegisterNodeManagerRequestPBImpl();
original.setHttpPort(8080);
original.setNodeId(getNodeId());
Resource resource = recordFactory.newRecordInstance(Resource.class);
resource.setMemory(10000);
resource.setVirtualCores(2);
original.setResource(resource);
RegisterNodeManagerRequestPBImpl copy = new RegisterNodeManagerRequestPBImpl(
original.getProto()); assertEquals(8080, copy.getHttpPort());
assertEquals(9090, copy.getNodeId().getPort());
assertEquals(10000, copy.getResource().getMemory());
assertEquals(2, copy.getResource().getVirtualCores()); } }
  • TestResourceTrackerPBClientImpl:

public class TestResourceTrackerPBClientImpl {

    private static ResourceTracker client;
private static Server server;
private final static org.apache.hadoop.yarn.factories.RecordFactory recordFactory = RecordFactoryProvider
.getRecordFactory(null); @BeforeClass
public static void start() { System.out.println("Start client test"); InetSocketAddress address = new InetSocketAddress(0);
Configuration configuration = new Configuration();
ResourceTracker instance = new ResourceTrackerTestImpl();
server = RpcServerFactoryPBImpl.get().getServer(ResourceTracker.class, instance, address, configuration, null,
1);
server.start(); client = (ResourceTracker) RpcClientFactoryPBImpl.get().getClient(ResourceTracker.class, 1,
NetUtils.getConnectAddress(server), configuration); } @AfterClass
public static void stop() { System.out.println("Stop client"); if (server != null) {
server.stop();
}
} /**
* Test the method registerNodeManager. Method should return a not null
* result.
*
*/
@Test
public void testResourceTrackerPBClientImpl() throws Exception {
RegisterNodeManagerRequest request = recordFactory.newRecordInstance(RegisterNodeManagerRequest.class);
assertNotNull(client.registerNodeManager(request)); ResourceTrackerTestImpl.exception = true;
try {
client.registerNodeManager(request);
fail("there should be YarnException");
} catch (YarnException e) {
assertTrue(e.getMessage().startsWith("testMessage"));
} finally {
ResourceTrackerTestImpl.exception = false;
} } /**
* Test the method nodeHeartbeat. Method should return a not null result.
*
*/ @Test
public void testNodeHeartbeat() throws Exception {
NodeHeartbeatRequest request = recordFactory.newRecordInstance(NodeHeartbeatRequest.class);
assertNotNull(client.nodeHeartbeat(request)); ResourceTrackerTestImpl.exception = true;
try {
client.nodeHeartbeat(request);
fail("there should be YarnException");
} catch (YarnException e) {
assertTrue(e.getMessage().startsWith("testMessage"));
} finally {
ResourceTrackerTestImpl.exception = false;
} } public static class ResourceTrackerTestImpl implements ResourceTracker { public static boolean exception = false; public RegisterNodeManagerResponse registerNodeManager(RegisterNodeManagerRequest request)
throws YarnException, IOException {
if (exception) {
throw new YarnException("testMessage");
}
return recordFactory.newRecordInstance(RegisterNodeManagerResponse.class);
} public NodeHeartbeatResponse nodeHeartbeat(NodeHeartbeatRequest request) throws YarnException, IOException {
if (exception) {
throw new YarnException("testMessage");
}
return recordFactory.newRecordInstance(NodeHeartbeatResponse.class);
} }
}

4.截图预览

  接下来,我们使用JUnit去测试代码,截图预览如下所示:

  • 对testRegisterNodeManagerRequestPBImpl()方法的一个DEBUG调试

  • testResourceTrackerPBClientImpl()方法的DEBUG调试

  这里由于设置exception的状态为true,在调用registerNodeManager()时,会打印一条测试异常信息。

if (exception) {
  throw new YarnException("testMessage");
}

5.总结

  在学习Hadoop YARN的RPC时,可以先了解Hadoop的RPC机制,这样在接触YARN的RPC的会比较好理解,YARN的RPC只是其中的一部分,后续会给大家分享更多关于YARN的内容。

6.结束语

  这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

Hadoop2源码分析-YARN RPC 示例介绍的更多相关文章

  1. Hadoop2源码分析-RPC探索实战

    1.概述 在<Hadoop2源码分析-RPC机制初识>博客中,我们对RPC机制有了初步的认识和了解,下面我们对Hadoop V2的RPC机制做进一步探索,在研究Hadoop V2的RPC机 ...

  2. Hadoop2源码分析-RPC机制初识

    1.概述 上一篇博客,讲述Hadoop V2的序列化机制,这为我们学习Hadoop V2的RPC机制奠定了基础.RPC的内容涵盖的信息有点多,包含Hadoop的序列化机制,RPC,代理,NIO等.若对 ...

  3. Hadoop2源码分析-HDFS核心模块分析

    1.概述 这篇博客接着<Hadoop2源码分析-RPC机制初识>来讲述,前面我们对MapReduce.序列化.RPC进行了分析和探索,对Hadoop V2的这些模块都有了大致的了解,通过对 ...

  4. Hadoop2源码分析-YARN 的服务库和事件库

    1.概述 在<Hadoop2源码分析-YARN RPC 示例介绍>一文当中,给大家介绍了YARN 的 RPC 机制,以及相关代码的演示,今天我们继续去学习 YARN 的服务库和事件库,分享 ...

  5. Hadoop2源码分析-MapReduce篇

    1.概述 前面我们已经对Hadoop有了一个初步认识,接下来我们开始学习Hadoop的一些核心的功能,其中包含mapreduce,fs,hdfs,ipc,io,yarn,今天为大家分享的是mapred ...

  6. Hadoop2源码分析-准备篇

    1.概述 我们已经能够搭建一个高可用的Hadoop平台了,也熟悉并掌握了一个项目在Hadoop平台下的开发流程,基于Hadoop的一些套件我们也能够使用,并且能利用这些套件进行一些任务的开发.在Had ...

  7. SparkRPC源码分析之RPC管道与消息类型

    SparkRPC源码分析之RPC管道与消息类型我们前面看过了netty基础知识扫盲,那我们应该明白,ChannelHandler这个组件内为channel的各种事件提供了处理逻辑,也就是主要业务逻辑写 ...

  8. Hadoop2源码分析-Hadoop V2初识

    1.概述 在完成分析Hadoop2源码的准备工作后,我们进入到后续的源码学习阶段.本篇博客给大家分享,让大家对Hadoop V2有个初步认识,博客的目录内容如下所示: Hadoop的渊源 Hadoop ...

  9. Java并发包中Semaphore的工作原理、源码分析及使用示例

    1. 信号量Semaphore的介绍 我们以一个停车场运作为例来说明信号量的作用.假设停车场只有三个车位,一开始三个车位都是空的.这时如果同时来了三辆车,看门人允许其中它们进入进入,然后放下车拦.以后 ...

随机推荐

  1. Android后台监控指定app的输入内容,抢红包,模拟点击原理

    Android开启辅助功能之后可以用AccessibilityService 去后台监控指定的app的输入内容,也可以监控到app的动作 以及通知栏的动作, 抢红包其实就根据通知栏出现了红包的通知消息 ...

  2. 四 分析easyswoole源码(启动服务&Cache组件原理)

    前文提到的在系统设置Cache组件 Cache::getInstance()的时候,会去调用processManager去创建Cache的进程,然后以管道通信的方式进行设置缓存和获取缓存. Cache ...

  3. Step by Step Guide on Yanhua ACDP Clear BMW EGS ISN

    Yanhua Mini ACDP authorize new function on BMW EGS ISN clearing.So here UOBDII want to share this st ...

  4. Mouse Detected Problem

    通常分三种情形: 鼠标完全不工作鼠标工作一段时间后不工作鼠标的按钮或者滚轮不工作 必要提交信息:1.鼠标的具体厂商和型号2.鼠标连接PC方式:串口.PS/2.USB或无线USB等:3.鼠标的工作机制: ...

  5. 【轻松前端之旅】​CSS选择器中的空格与尖括号有何区别?

    CSS选择器中的空格与尖括号有何区别? 例子1: .a .b { margin: 0; } 空格隔开a和b,选择所有后代元素. 例子2: .a>.b { margin: 0; } 尖括号隔开a和 ...

  6. linux_vim编辑文件无法高亮显示解决方法

    打开/etc/vimrc(/etc/vim/vimrc不同版本,可能不一样) 在文档最后添加下面内容 syntax on 如图所示:我添加了高亮显示和显示行数 syntax on set nu 修改完 ...

  7. Log4J日志整合及配置详解

    Log4j有三个主要的组件:Loggers(记录器),Appenders (输出源)和Layouts(布局).这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出.综合使用这三个组件可以轻松 ...

  8. w7 全网架构-rsync-备份

    准备 1.从安装系统开始准备 安装过程中添加网卡 eth0 ip 10.0.0.210 netmask 24 gateway 10.0.0.254 eth1 ip 172.16.1.210 netma ...

  9. 1001. A+B Format 字符串

    题目及答案链接 https://www.liuchuo.net/archives/1888 c++ 有关 字符串 和各种类型的转换 #include <string> string a; ...

  10. Instruments Time Profiler时,无法定位代码,如何破?

    都是地址符号,往深里也一直是地址符号,根本没法判断是哪些代码的执行时间 解决办法: 选下面的.