HDFSRPC协议详解

本文主要阐述HDFSRPCserver端一个socket连接接收字节流的构成,帮助读者理解HDFSRPC协议。注意hadoop版本为3.1.1。

写在前面

  1. 关于proto写入和读取,使用writeDelimitedTo和read,应该是通用的方式,不作过多的介绍。

  2. 处理rpc各种情况以后server都会使用统一的应答格式(包含错误与正确),即

RpcResponseHeaderProto+Message(rpc调用结果,错误时为NULL)
message RpcResponseHeaderProto {/*** RpcStastus - success or failure* The reponseHeader's errDetail,  exceptionClassName and errMsg contains* further details on the error**/required uint32 callId = 1; // callId used in Requestrequired RpcStatusProto status = 2;optional uint32 serverIpcVersionNum = 3; // Sent if success or failoptional string exceptionClassName = 4;  // if request failsoptional string errorMsg = 5;  // if request fails, often contains strack traceoptional RpcErrorCodeProto errorDetail = 6; // in case of erroroptional bytes clientId = 7; // Globally unique client IDoptional sint32 retryCount = 8 [default = -1];
}

RpcStatus的枚举类,注意当使用FATAL时,connection会关闭

 enum RpcStatusProto {SUCCESS = 0;  // RPC succeededERROR = 1;    // RPC or error - connection left open for future callsFATAL = 2;    // Fatal error - connection closed}

RPC错误的枚举类

enum RpcErrorCodeProto {// Non-fatal Rpc error - connection left open for future rpc callsERROR_APPLICATION = 1;      // RPC Failed - rpc app threw exceptionERROR_NO_SUCH_METHOD = 2;   // Rpc error - no such methodERROR_NO_SUCH_PROTOCOL = 3; // Rpc error - no such protocolERROR_RPC_SERVER  = 4;      // Rpc error on server sideERROR_SERIALIZING_RESPONSE = 5; // error serializign responseERROR_RPC_VERSION_MISMATCH = 6; // Rpc protocol version mismatch// Fatal Server side Rpc error - connection closedFATAL_UNKNOWN = 10;                   // unknown Fatal errorFATAL_UNSUPPORTED_SERIALIZATION = 11; // IPC layer serilization type invalidFATAL_INVALID_RPC_HEADER = 12;        // fields of RpcHeader are invalidFATAL_DESERIALIZING_REQUEST = 13;     // could not deserilize rpc requestFATAL_VERSION_MISMATCH = 14;          // Ipc Layer version mismatchFATAL_UNAUTHORIZED = 15;              // Auth failed}

RPC如果成功,会在head写完后,紧接着写入rpc调用结果proto。

Rpc连接数据流说明

连接中接收的数据结构图

7byte4byte(int len)+RpcrequestconnectionContext4byte(int len)+Rpcrequest
connectionHeaderRpcrequestconnectionContextRpcrequest

connectionHeader

/*** The Rpc-connection header is as follows * +----------------------------------+* |  "hrpc" 4 bytes                  |      * +----------------------------------+* |  Version (1 byte)                |* +----------------------------------+* |  Service Class (1 byte)          |* +----------------------------------+* |  AuthProtocol (1 byte)           |      * +----------------------------------+*/

任何一个连接都会有connectionHeader,connectionHeader由7个字节组成,内容如上。

关于header的check:第一是check前4个字节是否为hrpc,第二是check version。Check version由于要兼顾老版本,处理起来会比较复杂。

当前正确的Version为9:

  // 1 : Introduce ping and server does not throw away RPCs// 3 : Introduce the protocol into the RPC connection header// 4 : Introduced SASL security layer// 5 : Introduced use of {@link ArrayPrimitiveWritable$Internal} in ObjectWritable to efficiently transmit arrays of primitives// 6 : Made RPC Request header explicit// 7 : Changed Ipc Connection Header to use Protocol buffers// 8 : SASL server always sends a final response// 9 : Changes to protocol for HADOOP-8990public static final byte CURRENT_VERSION = 9;

Version的错误处理:

String errMsg = "Server IPC version " + CURRENT_VERSION + " cannot communicate with client version " + clientVersion;
String errClassName = "org.apache.hadoop.ipc.VersionMismatch";

Version=1 不处理

Version=2

4byte(int = 0)1byte(boolean=true)Int+bytes(int为String长度)(String=errClassName)Int+bytes(String=errMsg)

Version=3~8

4byte(int = callId)4byte(int=-1)Int+bytes(int为String长度)(String=errClassName)Int+bytes(String=errMsg)

Version>9(如果前4个字节不为hrpc,也是此错误)

RpcStatusProto.FATAL

RpcErrorCodeProto.FATAL_VERSION_MISMATCH

errMsg

errClassName

AuthProtocol:

现有两个值:NONE(0),SASL(-33),现在只使用0,sasl在后续文章中会有解析。

processOneRpc

任何一个rpcRequest都是由head和body组成

Head的结构

message RpcRequestHeaderProto { // the header for the RpcRequestenum OperationProto {RPC_FINAL_PACKET        = 0; // The final RPC PacketRPC_CONTINUATION_PACKET = 1; // not implemented yetRPC_CLOSE_CONNECTION     = 2; // close the rpc connection}optional RpcKindProto rpcKind = 1;optional OperationProto rpcOp = 2;required sint32 callId = 3; // a sequence number that is sent back in responserequired bytes clientId = 4; // Globally unique client ID// clientId + callId uniquely identifies a request// retry count, 1 means this is the first retryoptional sint32 retryCount = 5 [default = -1];optional RPCTraceInfoProto traceInfo = 6; // tracing infooptional RPCCallerContextProto callerContext = 7; // call context
}

关于Head的check

必须有rpcOP;rpcOP必须为RPC_FINAL_PACKET;必须有rpcKind

Head中比较重要的是callId属性,callId<0为特殊包,callId>=0为正常请求包。

callId<0

callId=PING_CALL_ID 不处理只打印日志

callId=CONNECTION_CONTEXT_CALL_ID

一般接收完connectionHeader,第一个RPC就为connectionContext。

connectionContext的结构

message IpcConnectionContextProto {// UserInfo beyond what is determined as part of security handshake // at connection time (kerberos, tokens etc).optional UserInformationProto userInfo = 2;// Protocol name for next rpc layer.// The client created a proxy with this protocol nameoptional string protocol = 3;
}
message UserInformationProto {optional string effectiveUser = 1;optional string realUser = 2;
}

主要是注意用户,hdfs server会把用户名作为connection Map的key。

还要注意connectionContext每个连接一直有一个,并且接收完此rpc以后立刻会接收下个rpc。

callId=AuthProtocol.SASL.callId(-33)

后续安全文章介绍。

callId>=0

需要注意的是如果没有接收connectionContext,将不会接收callId>=0的rpcRequest,否则则报错。

Hdfs server会根据rpcRequest head中的rpcKind,把rpcRequest body变成对应的对象。

enum RpcKindProto {RPC_BUILTIN          = 0;  // Used for built in calls by testsRPC_WRITABLE         = 1;  // Use WritableRpcEngine RPC_PROTOCOL_BUFFER  = 2;  // Use ProtobufRpcEngine
}

例如当rpcKind=RPC_PROTOCOL_BUFFER

Body=RpcProtobufRequest

RpcProtobufRequest又由RequestHeaderProto和Message(body)组成

RequestHeaderProto的结构

message RequestHeaderProto {required string methodName = 1;required string declaringClassProtocolName = 2;required uint64 clientProtocolVersion = 3;
}

Message(body)一般就是方法的入参。

Server在启动的时候会注册需要用的ProtocolName列表和实现类。例如

ClientNamenodeProtocolPB

ClientNamenodeProtocolPB继承与ClientNamenodeProtocol.BlockingInterface,实际就是ClientNamenodeProtocol.proto中的service定义

service ClientNamenodeProtocol {rpc getBlockLocations(GetBlockLocationsRequestProto)returns(GetBlockLocationsResponseProto);rpc getServerDefaults(GetServerDefaultsRequestProto)returns(GetServerDefaultsResponseProto);...
}

ClientNamenodeProtocolPB会有自己的

ProtocolName(org.apache.hadoop.hdfs.protocol.ClientProtocol)和ProtocolVersion(1)。

RequestHeaderProto中包含了declaringClassProtocolName 和clientProtocolVersion 可以找到对应的协议已经实现类,并根据methodName 去调用对应的方法。例如getBlockLocations方法,如下图。

在此方法中最终的RpcProtobufRequest中的Message(body)会format成

GetBlockLocationsRequestProto对象,调用完成后会返回GetBlockLocationsResponseProto。返回格式具体参考统一返回。

rotocolVersion 可以找到对应的协议已经实现类,并根据methodName 去调用对应的方法。例如getBlockLocations方法,如下图。

[外链图片转存中…(img-PY9haIcM-1710299505785)]

在此方法中最终的RpcProtobufRequest中的Message(body)会format成

GetBlockLocationsRequestProto对象,调用完成后会返回GetBlockLocationsResponseProto。返回格式具体参考统一返回。

独立站原文

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/743379.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《智能便利,畅享便利柜平台的架构奇妙之旅》

便利柜平台作为一种智能化、便捷的自助服务解决方案&#xff0c;正在逐渐走进人们的生活。本篇博客将深入探讨便利柜平台的架构设计理念、优势和实践&#xff0c;帮助读者了解如何构建智能便利柜平台&#xff0c;提供更便捷的自助服务体验。 ### 便利柜平台架构设计 #### 1. …

Java8中Stream流API最佳实践Lambda表达式使用示例

文章目录 一、创建流二、中间操作和收集操作筛选 filter去重distinct截取跳过映射合并多个流是否匹配任一元素&#xff1a;anyMatch是否匹配所有元素&#xff1a;allMatch是否未匹配所有元素&#xff1a;noneMatch获取任一元素findAny获取第一个元素findFirst归约数值流的使用中…

数据结构入门篇 之 【双链表】的实现讲解(附完整实现代码及顺序表与线性表的优缺点对比)

一日读书一日功&#xff0c;一日不读十日空 书中自有颜如玉&#xff0c;书中自有黄金屋 一、双链表 1、双链表的结构 2、双链表的实现 1&#xff09;、双向链表中节点的结构定义 2&#xff09;、初始化函数 LTInit 3&#xff09;、尾插函数 LTPushBack 4&#xff09;、头…

单据分页的实现

单据分页的实现 1. AceWzcgfkjtMaintainProxy.java package nc.ui.jych.wzcgfkjt.ace.serviceproxy;import nc.bs.framework.common.NCLocator; import nc.itf.jych.IWzcgfkjtMaintain; import nc.ui.uif2.components.pagination.IPaginationQueryService; import nc.vo.jych.…

软考高级:信息系统开发方法2(形式化方法、统计过程方法等)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

RTC协议与算法基础 - RTP/RTCP

首先&#xff0c;需要说明下&#xff0c;webrtc的核心音视频传输是通过RTP/RTCP协议实现的&#xff0c;源码位于src/modules/rtp_rtcp目录下&#xff1a; 下面让我们对相关的内容基础进行简要分析与说明&#xff1a; 一、TCP与UDP协议 1.1、TCP协议 TCP为了实现数据传输的可…

【Python】新手入门学习:详细介绍依赖倒置原则(DIP)及其作用、代码示例

【Python】新手入门学习&#xff1a;详细介绍依赖倒置原则&#xff08;DIP&#xff09;及其作用、代码示例 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、Py…

如何将.txtpb在IDE中彩色高亮显示

1. 问题描述 文件内容片段如下&#xff0c;它采用了一种键值对的格式&#xff0c;其中还包括了注释。我们可以采用一种近似的语言色彩识别方案处理它&#xff0c;比如YAML或者Python的语法高亮规则&#xff0c;因为这两种语言在处理键值对和注释的表示上与内容片段相似。当然也…

【QT+QGIS跨平台编译】之七十三:【QGIS_Analysis跨平台编译】—【错误处理:字符串错误】

文章目录 一、字符串错误二、处理方法三、涉及到的文件一、字符串错误 常量中有换行符错误:(也有const char * 到 LPCWSTR 转换的错误) 二、处理方法 需要把对应的文档用记事本打开,另存为 “带有BOM的UTF-8” 三、涉及到的文件 涉及到的文件有: src\analysis\processin…

openssl3.2 - exp - 选择最好的内建椭圆曲线

文章目录 openssl3.2 - exp - 选择最好的内建椭圆曲线概述笔记将 openssl ecparam -list_curves 实现迁移到自己的demo工程备注END openssl3.2 - exp - 选择最好的内建椭圆曲线 概述 在openssl中使用椭圆曲线, 只允许选择椭圆曲线的名字, 无法给定椭圆曲线的位数. 估计每种椭…

深度学习armv8/armv9 cache的原理

文章目录 前言1、为什么要用cache?2、背景:架构的变化?2、cache的层级关系 ––big.LITTLE架构&#xff08;A53为例)3、cache的层级关系 –-- DynamIQ架构&#xff08;A76为例)4、DSU / L3 cache5、L1/L2/L3 cache都是多大呢6、cache相关的术语介绍7、cache的分配策略(alocat…

C++函数 加括号与不加括号

很多时候&#xff0c;我们会看到一些在创建对象时有的加括号有的不加括号 那么&#xff0c;这是什么情况呢&#xff1f; 总结&#xff1a;函数需要加上括号&#xff0c;加上括号会对函数初始化&#xff0c;不加括号可能导致未知错误 我们来验证一下。 1.基本数据类型不带括…

利用Python进行网络爬虫:Beautiful Soup和Requests的应用【第131篇—Beautiful Soup】

利用Python进行网络爬虫&#xff1a;Beautiful Soup和Requests的应用 在网络数据变得日益丰富和重要的今天&#xff0c;网络爬虫成为了获取和分析数据的重要工具之一。Python作为一种强大而灵活的编程语言&#xff0c;在网络爬虫领域也拥有广泛的应用。本文将介绍如何使用Pyth…

Elasticseach基础认识

ES的起源&#xff1f; Elasticsearch 是由 Elastic 公司创建 简称&#xff08;ES&#xff09; Elasticsearch 是一个分布式、免费和开放的搜索和分析引擎&#xff0c;适用于所有类型的数据&#xff0c;包括文本、数字、地理空间、结构化和非结构化数据。 Elasticsearch 基于 …

Oracle 主从切换脚本

一、 切换前预检查 1. dg_precheck_main_v1.4.sh #!/bin/bash#********************************************************************************** # Author: Hehuyi_In # Date: 2022年06月16日 # FileName: dg_precheck_main_v1.4.sh # # For sys user, execute the sc…

LLM之RAG实战(二十九)| 探索RAG PDF解析

对于RAG来说&#xff0c;从文档中提取信息是一种不可避免的场景&#xff0c;确保从源文件中提取出有效的内容对于提高最终输出的质量至关重要。 文件解析过程在RAG中的位置如图1所示&#xff1a; 在实际工作中&#xff0c;非结构化数据比结构化数据丰富得多。如果这些海量数据无…

如何使用vue定义组件之——子组件调用父组件数据

1.定义父子模板template <div class"container"><my-father></my-father><my-father></my-father><my-father></my-father><!-- 此处无法调用子组件&#xff0c;子组件必须依赖于父组件进行展示 --><!-- <my-…

数学实验_Matlab使用2_简单绘图

简单使用 x -pi * 2 : .1 : pi*2;y sin(x);plot(x, y); % 绘制普通图像plot(x, y, k-.*); % 绘制2维图像&#xff0c;线为实线&#xff0c;*为每个点&#xff08;Matlab的画图比较原始&#xff0c;就是简单的秒点画图&#xff09;grid on; % 打开网状格式% grid off; % 关闭…

SORA和大语言模型的区别

OpenAI的文生视频模型SORA与大语言模型&#xff08;LLM&#xff09;的主要区别在于它们的应用领域和处理的数据类型&#xff0c;数据处理能力、技术架构、多模态能力和创新点。SORA作为一款专注于视频生成的模型&#xff0c;展现了在处理视觉数据方面的独特优势和创新能力。 1…

R语言读取大型NetCDF文件

失踪人口回归&#xff0c;本篇来介绍下R语言读取大型NetCDF文件的一些实践。 1 NetCDF数据简介 先给一段Wiki上关于NetCDF的定义。 NetCDF (Network Common Data Form) is a set of software libraries and self-describing, machine-independent data formats that support…