haoop rpc服务端读取数据包源码解析注释

HadoopRPC源码解析 Hadoop是一个大数据处理平台,目前在大数据领域应用也非常广泛,刚好最近我们BI组在进行把底层数据仓库迁移到Hadoop平台,所以在工作之余开始去深入了解下hadoop内部实现以更好地应用它,在遇到问题的时候有更好的解决思路。本篇分享先介绍Hadoop领域中RPC框架的实现原理,后续会继续分析HDFS及MapReduce及Hive实现原理跟大家分享(hadoop版本1.0,JDK版本1.6)。 阅读详情

RPC包格式:


这图是从别人那拿过来的 留着自己看,主要是对如下这段代码的理解有帮助:

    /**
     * 请求报文:			4字节hrpc + 			1字节Current_version + 	1字节authMethod
     * 					4字节Header_len + 	connection_header
     * 					4字节Data_len + 		call.id + 				writable
     * 
     * connection_header长度不定  call.id + writable长度不等
     * 	
     * 返回报文:		call.id + 			status.state + 			writable
     * 																errorClass + error
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public int readAndProcess() throws IOException, InterruptedException {
      while (true) {
        /* Read at most one RPC. If the header is not read completely yet
         * then iterate until we read first RPC or until there is no data left.
         */    
        int count = -1;
        //读取hrpc信息
        if (dataLengthBuffer.remaining() > 0) {
          count = channelRead(channel, dataLengthBuffer);       
          if (count < 0 || dataLengthBuffer.remaining() > 0) 
            return count;
        }
      
        if (!rpcHeaderRead) {//一次连接 只会读一次
          //Every connection is expected to send the header.
          if (rpcHeaderBuffer == null) {
            rpcHeaderBuffer = ByteBuffer.allocate(2);
          }
          count = channelRead(channel, rpcHeaderBuffer);
          if (count < 0 || rpcHeaderBuffer.remaining() > 0) {
            return count;
          }
          //读取current_version信息
          int version = rpcHeaderBuffer.get(0);
          //读取authMethod(认证方法)信息
          byte[] method = new byte[] {rpcHeaderBuffer.get(1)};
          authMethod = AuthMethod.read(new DataInputStream(new ByteArrayInputStream(method)));
          dataLengthBuffer.flip();          
          if (!HEADER.equals(dataLengthBuffer) || version != CURRENT_VERSION) {
            //Warning is ok since this is not supposed to happen.
            LOG.warn("Incorrect header or version mismatch from " + hostAddress + ":" + remotePort +
                     " got version " + version + " expected version " + CURRENT_VERSION);
            return -1;
          }
          dataLengthBuffer.clear();
          if (authMethod == null) {
            throw new IOException("Unable to read authentication method");
          }
          if (isSecurityEnabled && authMethod == AuthMethod.SIMPLE) {
            AccessControlException ae = new AccessControlException("Authentication is required");
            setupResponse(authFailedResponse, authFailedCall, Status.FATAL, null, ae.getClass().getName(), ae.getMessage());
            responder.doRespond(authFailedCall);
            throw ae;
          }
          if (!isSecurityEnabled && authMethod != AuthMethod.SIMPLE) {
            doSaslReply(SaslStatus.SUCCESS, new IntWritable(SaslRpcServer.SWITCH_TO_SIMPLE_AUTH), null, null);
            authMethod = AuthMethod.SIMPLE;
            // client has already sent the initial Sasl message and we
            // should ignore it. Both client and server should fall back
            // to simple auth from now on.
            skipInitialSaslHandshake = true;
          }
          if (authMethod != AuthMethod.SIMPLE) {
            useSasl = true;
          }
          
          rpcHeaderBuffer = null;
          rpcHeaderRead = true;
          continue;
        }
        //读取connection连接信息及真正的Data信息
        if (data == null) {
          dataLengthBuffer.flip();
          dataLength = dataLengthBuffer.getInt();
       
          if (dataLength == Client.PING_CALL_ID) {//如果此RPC调用为ping则 直接返回
            if(!useWrap) { //covers the !useSasl too
              dataLengthBuffer.clear();
              return 0;  //ping message
            }
          }
          if (dataLength < 0) {
            LOG.warn("Unexpected data length " + dataLength + "!! from " + getHostAddress());
          }
          data = ByteBuffer.allocate(dataLength);
        }
        
        count = channelRead(channel, data);
        //当data没有空位置时 说明已经读完
        if (data.remaining() == 0) {
          dataLengthBuffer.clear();
          data.flip();
          if (skipInitialSaslHandshake) {
            data = null;
            skipInitialSaslHandshake = false;
            continue;
          }
          boolean isHeaderRead = headerRead;
          if (useSasl) {
            saslReadAndProcess(data.array());
          } else {//此处具体处理Data信息及Header信息
            processOneRpc(data.array());
          }
          data = null;
          if (!isHeaderRead) {//如果只读取了Header信息  继续循环读取Data信息
            continue;
          }
        }
        return count;
      }
    }

    private void processOneRpc(byte[] buf) throws IOException, InterruptedException {
      if (headerRead) {//读取Data信息
        processData(buf);
      } else {//读取Header信息
        processHeader(buf);
        headerRead = true;
        if (!authorizeConnection()) {
          throw new AccessControlException("Connection from " + this
              + " for protocol " + header.getProtocol()
              + " is unauthorized for user " + user);
        }
      }
    }

    private void processData(byte[] buf) throws  IOException, InterruptedException {
      DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf));
      int id = dis.readInt();                    // try to read an id
        
      if (LOG.isDebugEnabled())
        LOG.debug(" got #" + id);

      Writable param = ReflectionUtils.newInstance(paramClass, conf);//read param
      param.readFields(dis);        
        
      Call call = new Call(id, param, this);
      callQueue.put(call);              // queue the call; maybe blocked here
      incRpcCount();  // Increment the rpc count
    }

    /// Reads the connection header following version
    private void processHeader(byte[] buf) throws IOException {
      DataInputStream in = new DataInputStream(new ByteArrayInputStream(buf));
      header.readFields(in);
      try {
        String protocolClassName = header.getProtocol();
        if (protocolClassName != null) {
          protocol = getProtocolClass(header.getProtocol(), conf);
        }
      } catch (ClassNotFoundException cnfe) {
        throw new IOException("Unknown protocol: " + header.getProtocol());
      }
      
      UserGroupInformation protocolUser = header.getUgi();
      if (!useSasl) {
        user = protocolUser;
        if (user != null) {
          user.setAuthenticationMethod(AuthMethod.SIMPLE.authenticationMethod);
        }
      } else {
        // user is authenticated
        user.setAuthenticationMethod(authMethod.authenticationMethod);
        //Now we check if this is a proxy user case. If the protocol user is
        //different from the 'user', it is a proxy user scenario. However, 
        //this is not allowed if user authenticated with DIGEST.
        if ((protocolUser != null)
            && (!protocolUser.getUserName().equals(user.getUserName()))) {
          if (authMethod == AuthMethod.DIGEST) {
            // Not allowed to doAs if token authentication is used
            throw new AccessControlException("Authenticated user (" + user
                + ") doesn't match what the client claims to be ("
                + protocolUser + ")");
          } else {
            // Effective user can be different from authenticated user
            // for simple auth or kerberos auth
            // The user is the real user. Now we create a proxy user
            UserGroupInformation realUser = user;
            user = UserGroupInformation.createProxyUser(protocolUser
                .getUserName(), realUser);
            // Now the user is a proxy user, set Authentication method Proxy.
            user.setAuthenticationMethod(AuthenticationMethod.PROXY);
          }
        }
      }
    }

 具体查看链接:http://fengshenwu.com/blog/2012/11/13/hadoop-rpc_develop/

我的hadoop源码(有一些我看代码时留下的注释):https://github.com/heipacker/hadoop-1.0.3-linux

【RPC】RPC基础(二)RPC协议 文章目录RPC核心原理1. RPC基础1.2 RPC协议为什么设计RPC协议如何设计RPC协议可扩展协议的设计思考 RPC核心原理 1. RPC基础 1.2 RPC协议 RPC协议和HTTP协议一样都属于应用层协议 协议的作用: ​ 协议就像是文章中的标点符号、段落格式等规定,有了这些我们能明白一句话和一个段落到那里结束。RPC调用中,请求信息转换为二进制写入本地Socket,再通过网卡发往网络设备。二进制码有可能被划分为多个不同数据块进行发送,发送过程中还可能与其他数据块进行合并,协议的作用就是标定接收方 阅读详情

相关推荐

Hadoop RPC通信机制实战实例详解

在Hadoop分布式架构中,远程过程调用(RPC)不仅是组件间通信的桥梁,更是系统可扩展性、模块解耦和跨节点协同的关键支撑。其中,协议接口定义与方法暴露机制构成了整个RPC体系的基础层。一个清晰、规范且具备版本控制能力的协议设计,是确保服务端稳定提供能力、客户端准确发起调用的前提。本章将深入剖析Hadoop RPC框架下如何通过Java接口定义远程服务契约,以及这些接口如何被服务端“暴露”为可被远程访问的端点。

weixin_33481022的博客 1154

Hadoop源码分析5: RPC基本线程

1. 数据记录FileStatus public class FileStatus implements Writable { private String filename; private long time; static { // register IPCFileStatus WritableFactories.setFac...

weixin_30764771的博客 333

告别配置烦恼!保姆级教程:在Windows 10/11上为QT5.14.2配置MSVC2017编译器(附VS2022组件避坑指南)

本文提供了一份详细的保姆级教程,指导如何在Windows 10/11上为QT5.14.2配置MSVC2017编译器,包括VS2022组件避坑指南。从环境准备到关键配置,再到调试工具验证和Qt Creator中的编译器设置,一步步解决常见问题,帮助开发者快速搭建稳定可靠的开发环境。

weixin_30615767的博客 501

20241206-解决hadoop报错:org.apache.hadoop.ipc.RpcException: RPC response exceeds maximum data length

Hadoop RPC报错解决方法摘要 当遇到"RPC response exceeds maximum data length"错误时,可采取以下措施: 使用jps命令检查namenode和datanode进程状态,确保已启动(未启动时执行start-dfs) 检查core-site.xml配置文件中fs.default.name属性,确认请求地址正确无误

…… 1420

《Linux运维总结:Ubuntu22.04忘记root密码解决方案》

《Linux运维总结:Ubuntu22.04忘记root密码解决方案》

东城绝神 4459

告别切换烦恼!用Parallels Desktop的Host-Only网卡,在macOS上直接访问虚拟机里的公司内网

本文详细介绍了如何在macOS上使用Parallels Desktop的Host-Only网卡直接访问虚拟机内的公司内网,告别频繁切换操作系统的烦恼。通过配置Host-Only网络模式,实现主机与虚拟机的安全高效通信,特别适合需要频繁访问内网资源的IT从业者。文章包含分步指南、自动化脚本和常见问题解决方案,帮助用户优化工作流程。

weixin_28739079的博客 361

hadoop报错 is longer than maximum configured RPC length 67108864

hadoop 2.7.3 集群,出现录入数据延迟高的问题,namenode日志中有报错信息: is longer than maximum configured RPC length 67108864 报错原因: ipc实际通讯的数据包大于默认最大的数据包配置64MB 解决办法: 提高这个参数到128MB 1、在下面3个配置中同时加上 vi /data/usr/hadoop-2.7.3/share/doc/hadoop/hadoop-project-dist/hadoop-common/core-d.

duanbiren123的博客 1409

基于PyQt5的ROS移动机器人的人机交互UI界面

每次做实验的时候,手动rosrun,roslaunch太过麻烦,通过ui界面的话,只需要点点按钮就可以啦 ros_car_py包括运动,建图,导航,ui界面的程序全部打包上传,相互依赖关系见ros_car_py包。 import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets imp...

工大机器人工作室 7365

安装pig时遇到的问题

下载pig-0.8.1的安装包,解压到安装路径后,设置好HADOOP_CONF_DIR  和HADOOP_HOME,然后运行bin/pig 出现错误,错误信息如下: ERROR org.apache.pig.Main - ERROR 2999: Unexpected internal error. Failed to create DataStorage 到namenode上去查看pig连接

竹叶青 的专栏 2700

无线自组织网络基础知识

参考书籍:《无线自组织网络路由协议及应用》 目录第一章 绪论1.1 无线自组织网络概述1.1.1 无线自组织网络的定义及分类1.1.2无线自组织网络的主要特点1.1.3无线自组织网络的应用与发展1.无线自组织网络的应用2.无线自组织网络的起源和发展1.2典型的无线自组织网络1.2.1移动Ad Hoc网络1、移动Ad Hoc网络的定义2.移动AdHoc网络的特点3.移动Ad Hoc网络的应用1.2....

逸凌Time 2万+

LVGL字体优化实战:如何将中文字库放到外部SPI Flash并动态加载(节省内部RAM)

本文详细介绍了LVGL在嵌入式UI开发中如何通过外部SPI Flash存储中文字库并动态加载,以节省内部RAM资源。通过对比不同存储介质和字库格式,提供多种实现方案及性能优化技巧,帮助开发者在资源受限设备上实现高效的中文显示。

weixin_28693683的博客 341

Hadoop RPC流程

最近开始看Hadoop源码,本来想对照着《Hadoop技术内幕》看的,但是发现那本书对应的Hadoop版本太老了,还是基于1.x的,构建工具用的Ant,所以没有完全对照书看。目前Hadoop最新的stable版本为2.8.0-RC1,本文以及之后的Hadoop源码相关的博文都以这个版本为基础。另外写的可能会糙一些。

Harper 696

h5支付不能打开支付宝 ios_iOS支付宝H5支付无法返回APP解决方案

本文前大段在讲楼主是如何解决这个问题的,以及中间遇到的麻烦。赶时间的同学可以直接看最后的 最终解决方案。在讨论之前,我们先看看官方文档上的一句话:注意:在iOS系统中,唤起支付宝App支付完成后,不会自动回到浏览器或商户APP。用户可手工切回到浏览器或商户APP;支付宝H5收银台会自动跳转回商户return_url指定的页面。what? 官方直接跟我们说GG了?楼主不甘心,还是想尝试一下。借鉴之前...

weixin_39864101的博客 854

Hadoop的RPC机制_Client组件

来源:http://blog.youkuaiyun.com/xhh198781/article/details/7268298  来源:http://weixiaolu.iteye.com/blog/1504898  源码级强力分析hadoop的RPC机制         在Client中,因为与服务器的每一次连接不仅会产生网络延迟,而且也会占用大量的系统资源,所以在Client内部设计了一个连接池

李战磊专栏 2296

探索数据库领域 SQL 的 JSON 数据处理技巧

在当今数字化时代,JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,被广泛应用于各种领域,如 Web 应用、移动应用、大数据处理等。数据库作为数据存储和管理的核心,需要具备处理 JSON 数据的能力。本文章的目的在于深入探索 SQL 语言在数据库中处理 JSON 数据的技巧,涵盖从基础的 JSON 数据查询到复杂的 JSON 数据操作,帮助读者全面了解和掌握 SQL 处理 JSON 数据的方法。

2502_91592937的博客 924

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Hadoop RPC通信协议

Hadoop RPC客户端(Client)向RPC建立连接时向RPC服务器发送两部分内容:RPC Header和Header。RPC Header的格式如下: private void writeRpcHeader(OutputStream outStream) throws IOException { DataOutputStream out = new DataOutputStream

坐禅小和尚的专栏 2980

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Hadoop技术内幕之RPC框架解析(上)

网络通信模块是分布式系统中最底层的模块。它直接支撑了上层分布式环境下复杂的进程间通信逻辑,是所有分布式系统的基础。远程过程调用(RPC)是一种常用的分布式网络通信协议。它允许运行于一台计算机的程序调用另一台计算机的子程序,同时将网络通信细节隐藏起来,使得用户无须额外地为这个交互作用编程。Hadoop RPC框架概述对于Hadoop RPC,具有以下几个特点: 透明性:所有RPC框架的最根本特征。 高

yuyurenjie的博客 1813

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Hadoop RPC源码分析

[java] view plaincopy Hadoop RPC :与传统的RPC程序相似,分为Server端和Client端二个部分,下面将分别介绍其工作机制      1.Client端分析:   |-->Client(Classextends Writable> valueClass, Configuration conf, SocketFactory f

csr_hema的专栏 445

hadoop-3.1.1-RPC(1)

RPC :Remote Procedure Call 本地程序像调用本地方法一样调用远程计算机上的应用程序,采用客户端/服务器模式,请求程序是客户端,服务提供程序就是服务端 hadoop RPC架构 RPC类结构 RPC类提供一个统一的接口,客户端通过getProxy()方法获取代理对象,服务端通过内部类Builder.build()方法构造server。 RPC类在namenode中的使用 构造server org.apache.hadoop.hdfs.server.namenode.NameNo

qq_29989725的博客 342

hadoop 可能遇到的错误

1.question 2011-08-15 13:07:42,558 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: server0/192.168.2.10:9000. Already tried 5 time(s). 2011-08-15 13:07:42,558 INFO org.ap...

chunguo.wang 655

Hadoop3.2.1 【 HDFS 】源码分析 : RPC原理 [九] RPC 请求格式

■ length: 每个protobuf类型的数据都包含一个length字段, 这是因为, 在HDFS写入操作时, 使用了writeDelimitedTo()方法。 这个方法会先写入数据的length, 然后再写入数据。 ■ RpcRequestHeaderProto: RPC调用头域, 保存了callId、 clientId、 rpcKind等重要信息。 服务器发回的响应消息中会带回...

张伯毅的专栏 2068

RPC模式

System.out.println("从服务端返回用户密码:" + dto.getUser().getPassword());System.out.println("从服务端返回用户账号:" + dto.getUser().getAccount());System.out.println("当前在线人数:" +Server.getOnlineHandler().size());if(dto.getBizType().equals(BizType.登录成功)) {//设置客户端任务状态为false,

Coder-coco的博客 127

Hadoop RPC通信Server端的流程分析

前2天刚刚小小的分析下Client端的流程,走的还是比较通顺的,但是RPC的服务端就显然没有那么简单了,毕竟C-S这种模式的,压力和重点都是放在Server端的,所以我也只能做个大概的分析,因为里面细节的东西太多,我也不可能理清所有细节,但是我会集合源代码把主要的流程理理清。如果读者想进一步学习的话,可自行查阅源码。            Server服务端和Client客户端在某些变量的定义上

走在前往架构师的路上 3360

Hadoop与RPC通讯格式需求(19)

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33896726的博客 83

可能是最好的RPC中文文档

一个计算机通信协议,基于扩展常规或本地过程调用的概念。因此被调用过程不必与调用过程存在于同一地址空间中。这两个进程可能位于同一系统上,也可能位于不同的系统上,并通过网络连接它们。程序员就像调用本地程序一样,无需额外地为这个交互编程(无需关注细节)。上图表示两个联网系统之间 RPC 调用流程。客户端进行过程调用,向服务器发送请求并阻塞等待,直到收到答复或请求超时。当请求到达时,服务器执行对应的请求过程,并将执行结果发送给客户端。客户端收到应答消息后被唤醒继续运行。被调用过程的唯一规范。

kjl167的博客 558

RPC 核心原理理论分析

RPC 的全称是 Remote Procedure Call,即远程过程调用。简单解读字面上的意思,远程肯定是指要跨机器而非本机,所以需要用到网络编程才能实现。从业务角度来看,RPC有两个作用从技术角度来看,RPC有这几个作用。

CoLiuRs 1177
上一篇: java线程同步原理、wait,notify的用法及与sleep的区别
下一篇: ProtoBuf例子及google ProtoBuf开发者指南
heipacker
博客等级 码龄17年 9粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值