浩克网 手游攻略 软件教程 谷歌开源项目(google rpc框架)

谷歌开源项目(google rpc框架)

时间:2025-04-22 10:02:32 来源:网络整理 浏览:0

作者:达图胡,腾讯IEG后期开发工程师

在广告系统的实践中,精细调度服务调用基于gRPC协议的TF-Serving在线推理服务。我相信很多服务都使用了gRPC相关语言的框架来进行服务调用。

特别是基于Google Cloud的sea业务的服务调用,无法避免gRPC,所以需要了解gRPC的原理。本文简单介绍了gRPC的调用过程,逐渐了解了gRPC。

概述gRPC是Google推出的开源高性能RPC框架。默认情况下,protoBuf用于序列化和反序列化,消息基于HTTP/2传输。

它带来了诸如多路复用具有多个请求的TCP连接(所谓的多路复用)、双向流、流控制、报头压缩等特性。GRPC目前有c、Go、JAVA等语言版本。

相应的开发框架如gRPC,gRPC-Go,gRPC-JAVA。在gRPC中,开发者可以像调用本地方法一样,通过gRPC客户端调用远程机器上gRPC服务的方法。

gRPC客户端封装了HTTP/2协议数据帧的封装和网络层的通信细节,把复杂留给了框架本身,为用户提供了便利。GRPC基于定义服务的设计概念,

及其远程调用的方法(方法名、参数输入、参数输出)。这个方法的业务逻辑是在gRPC服务器上实现的,远程客户端对这个RPC方法的调用是在gRPC服务器上处理的。

gRPC客户端也有这个RPC方法的存根。gRPC的客户端和服务器可以用任何支持gRPC的语言实现。例如,gRPC服务器可以用C语言编写。

供Ruby语言的gRPC客户端和JAVA语言的gRPC客户端调用,如下图所示:

GRPC默认使用ProtoBuf来序列化和反序列化请求/响应,这使得传输的请求体和响应体比JSON和其他序列化方法更小更轻。GRPC基于HTTP/2协议传输消息,

HTTP/2具有复用和头压缩的特点。基于HTTP/2的帧设计,将多个请求复用成一个TCP连接,基本解决了HTTP/1.1的队列头阻塞问题。

与HTTP/1.1相比,它带来了巨大的性能提升。下面简单介绍一下HTTP/2。

HTTP/2简介HTTP是一个成功的应用层协议。但是,由于HTTP的队列头阻塞,对基于HTTP的应用程序的性能有很大的影响。队列头阻塞意味着必须先处理顺序请求中的一个请求,然后才能处理其他后续请求。

当一个请求被阻塞时,会给应用程序带来延迟。虽然HTTP/1.1提供了请求管道操作,但是由于HTTP协议的限制,

不可能消除HTTP的队列头阻塞造成的延迟。为了减少延迟,HTTP客户端需要与服务器建立多个连接,实现请求的并发处理,减少延迟。然而,在高并发的情况下,大量的网络连接可能耗尽系统资源,

您可以使用连接池模式仅维护固定数量的连接,这可以防止服务耗尽资源。连接池连接数的设置在性能要求高的应用中也是一个挑战,需要根据实际机器配置的压力测试来确定。此外,HTTP头字段重复且冗长。

网络传输不必要的冗余消息,初始TCP拥塞窗口很快被填满。处理大量请求的TCP连接将导致很大的延迟。HTTP/2优化了HTTP的消息定义,

它允许在同一网络连接上并发和交错处理请求和响应,并通过减少HTTP头字段的重复传输和压缩HTTP头来提高处理性能。HTTP每次在网络上传输都会携带很多冗余的头信息,比如通信资源、浏览器属性等等。

为了减少这些重复传输的开销,HTTP/2压缩了这些报头字段:

基于HTTP/2协议的客户机和服务器使用“头表”来跟踪和存储发送的键值对。对于相同的键-值对数据,没有必要发送每个请求和响应。标题表在HTTP/2连接的有效期内总是存在的,

客户端和服务器共同维护更新;每个新的HTTP头键值对或者附加或者替换头表的原始值。例如,在HTTP/1.x中有两个请求,

请求1和请求2都应该发送所有的报头数据;在HTTP/2中,请求1发送所有的头数据,请求2只发送改变的头数据,这样可以减少冗余数据,降低网络开销。如下图所示:

这里有另一个例子来说明HTTP/1.x和HTTP/2在处理请求方面的区别。一个浏览器需要请求三个文件,/index.html,styles.css和/scripts.js,才能打开网络。

基于HTTP/1.x建立的连接只能先请求/index.html,得到响应后再请求styles.css,得到响应后再获取/scripts.js。

而基于HTTP/2的网络连接,在获得/index.html后,可以同时获得styles.css和/scripts.js文件,如下图所示:

HTTP/2对服务资源和网络更友好,与处理相同数量级请求的HTTP/1.x相比,需要建立更少的TCP连接。这主要是由于HTTP/2使用二进制数据帧来传输数据。

使得一个TCP 连接可以同时处理多个请求而不用等待一个请求处理完成再处理下一个。从而充分发掘了TCP 的并发能力。

HTTP/2 帧在HTTP/2 中,帧是网络通信的基本单位,HTTP/2 主要定义了10 种不同的帧类型,每种帧类型在建立和管理连接或者单个stream 流有不同的作用。

不同的帧类型都有公共字段:Length(3 字节),Type(1 字节), Flags(1 字节), Stream Identifier(4 字节) 和Frame Payload(变长)。

HTTP/2 帧都以固定的9 字节大小作为帧头,后面跟着变长的包体Paylload。如下图所示:

帧头字段说明:

Length 帧的数据(Frame Payload)长度,不包括帧头长度,3 个字节(24bit), 帧最大长度为124 - 1(16383);Type 帧类型,

1 个字节(8bit), 目前HTTP/2 定义了10 中帧类型,常见的帧类型有DATA 帧、HEADERs 帧、SETTINGS 帧等,10 种帧类型如下图所示:Flags 帧标志,

1 个字节(8bit),没有特定帧类型的帧标志应该被忽略,在发送时帧标志需要保持未设置(0x0).常见的标志位有END_HEADERS 表示HTTP/2 数据头结束,

相当于HTTP 头后的空行(“\r\n”),END_STREAM 表示单方向数据发送结束(即EOS,End of Stream),

相当于HTTP/1.x 里Chunked 分块结束标志(“0\r\n\r\n”);R 保留字段1bit,发送时保持未设置(0x0),接收时忽略;Stream Identifier 流标识符,

31bit. 一个无符号整数。由客户端发起的Stream 数据流用奇数编号ID 的流标识符;由服务器发起的数据流使用偶数编号ID 的流标识符。

流标识符零(0x0)用于连接控制消息;零流标识符不能用于建立新的stream 流。HTTP/2 请求模型HTTP/2 的请求模型如下图所示:

Connection 连接:对应一个TCP 连接,可以承载一个或者多个Stream。Stream 流:对应一个双向通信的数据流,可以承载一个或者多个Message。

每个数据流都有一个唯一的流标识符和可选的优先级信息,用于承载双向消息。Stream 流有几个重要特性:

更多参考:https://github.com/halfrost/Halfrost-Field/blob/master/contents/Protocol/HTTP:2-HTTP-Frames-Definitions.md

gRPC 协议前面对HTTP/2 帧作了简要说明,这节开始介绍gRPC 协议,gRPC 基于HTTP/2/协议进行通信,使用ProtoBuf 组织二进制数据流,gRPC 的协议格式如下图:

从以上图可知,gRPC 协议在HTTP 协议的基础上,对HTTP/2 的帧的有效包体(Frame Payload)做了进一步编码:gRPC 包头(5 字节)+gRPC 变长包头,其中:

5 字节的gRPC 包头由:1 字节的压缩标志(compress flag)和4 字节的gRPC 包头长度组成;gRPC 包体长度是变长的,

其是这样的一串二进制流:使用指定序列化方式(通常是ProtoBuf)序列化成字节流,再使用指定的压缩算法对序列化的字节流压缩而成的。如果对序列化字节流进行了压缩,gRPC 包头的压缩标志为1。

对比tRPC 协议可知,gRPC 的帧头和包头比tRPC 协议帧头和包头要小,当然HTTP/2 的帧类型更复杂一些。

tRPC 协议帧定义如下图:gRPC 调用抓包分析下面基于官方提供的gRPC-Go helloword 例子,使用Wireshark 分析通过tcpdump 抓包gRPC 调用的报文,

加深对gRPC 协议的理解。

下载地址:https://www.wireshark.org/;安装Go 环境;安装protoc-gen-go: go get -u github.com/golang/protobuf/protoc-gen-go;下载grpc-go/examples/helloworld gRPC-Go 的helloword Go 工程。

运行helloword 的客户端greeter_client:完成一次调用,tcpdump 抓到一次调用的报文,保存为grpc.cap。

3.Wireshark 配置打开Wireshark 主面板,

选择ProtoBuf 文件路径:Wireshark--Preferences--Protocols--Protobuf--Protobuf Search Paths。

选择helloworld 的proto 文件地址。

Wireshark 打开grpc.cap 文件,选中greeter_client 发送端口号和greeter_server 发送端口号的报文记录,右键Decode As.为HTTP/2:

Wireshark 过滤框输入HTTP2 就可得到一次完整的gRPC 调用细节:

本文分析中抓包的一个帧序列例子:Magic--SETTINGS(双向四个)--HEADERS--DATA(GRPC-PROTOBUF)--WINDOW_UPDATE,PING--PING--HEADERS,DATA,HEADERS--WINDOW_UPDATE,PING--PING。

1)客户端发送Magic 帧Magic 帧的为固定内容:PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n。

如下图所示:客户端发送Magic 帧后双方就会使用HTTP/2 相关协议进行通信。

2)客户端和服务端发SETTINGS 帧接着Magic 帧后,接下来就是发送SETTINGS 帧,SETTINGS 帧主要用于传递影响两端网络通信的配置参数,以及确认收到这些参数。

客户端和服务器首先发两个SETTINGS 帧传递配置参数信息,接着服务端发了一个确认的SETTINGS 帧后,客户端也发出了一个确认的SETTINGS 帧:a.客户端发第一个SETTINGS,

帧类型=0x4,帧标志为0x00, 流标识符为0:

b.服务端向客户端回了一个SETTINGS 帧,帧类型=0x4,帧标志为0x00, 流标识符为0,同时告诉客户端,服务端愿意接收的最大帧大小为16384 bytes。同时我们看到,

SETTINGS 帧的参数类型为SETTINGS_MAX_FRAME_SIZE(0x5),参数类型表示服务端愿意接受的包体大小,初始值为16364 个字节。此外,SETTINGS 帧长度为6:

c.随后服务端再发出一个确认的SETTINGS 帧,帧类型=0x4,帧标志为0x01, 流标识符为0:

d.客户端收到服务端的确认SETTINGS 帧后,也发出一个SETTINGS 帧进行确认,帧类型=0x4,帧标志为0x01, 流标识符为0,

双方进行确认后下面就可以开始传输头帧(HEADERS)和数据帧(DATA)了:

3)客户端发送HEADERS 帧客户端和服务器双方发送SETTINGS 帧进行双方参数确认后,下一步客户端向服务端发送一个HEADERS 帧, 当前HEADERS 帧长度为92,

帧类型=0x1,帧标志为0x04(End Headers,

0=End Stream:False,1=End Headers:True,0=Padded:False,0=Priority:False),流标识符为1,

HEADERS 帧还额外带有Head Block Fragment 头块片段(header 列表是零个或多个字段的集合。当通过网络连接传输时,

使用HTTP 头压缩[COMPRESSION] 将header 列表序列化为header block 块。然后将序列化的header block 块分成字节流,

称为header 块片段);同时还可以看到一些HTTP 请求头(8 个)信息,比如:method:POST,scheme:http,

:path:/helloworld.Greeter/SayHello 等等,如下图所示:

gRPC 的包体内容为'who are you', 对应的protobuf 中message 的Name 字段承载的信息=WireType本身占1 个字节枚举值为2[string,编码0a]+value 长度本身占1 个字节[string 需要显式的告知value 长度]11 个字节(编码0b)+字段value 信息'who are you'11 个字节,

5)服务端发送WINDOW_UPDATE 帧和PING 帧客户端发完DATA 帧后,服务器先回复了两个帧,分别是WINDOW_UPDATE 帧和PING 帧,

WINDOW_UPDATE 帧主要用于流量控制。当前的WINDOW_UPDATE 帧的长度为4,帧类型为WINDOW_UPDATE(8),帧标志为0x00,流标志符为0,

Window Size Increment(流量窗口增量)为18(收到客户端发送的DATA 帧长度18)。PING 帧用于测量最小往返时间(RTT)以及确定连接是否存活。

当前PING 帧的长度为8,帧类型为PING(6),帧标志为0x00(ACK=False),流标志符为0。此次WINDOW_UPDATE 帧和PING 帧的发送情况如下图所示:

6)客户端回复PING 帧客户端收到服务器的PING 帧后,会回一个PING 帧确认(ACK=True)以及回复Pong 信息,当前PING 帧的长度为8,帧类型为PING(6),

帧标志为0x01(ACK=True),流标志符为0,Pong 信息为一串16 位的UUID 串,如下图所示:

7)服务端回复HEADERS 帧+DATA 帧(gRPC)+HEADERS 帧(终止流)服务端收到客户端的PING 帧确认客户端存活状态后,a. 首先是一个HEADERS 帧,

该帧的帧长度为14,帧类型Type 为HEADS(1),帧标志Flags 为End Headers(0x04),流标志符为1,HEAD 长度为54,head 数量为2,

分别为status: 200 OK、content-type:application/grpc;b. 然后是一个DATA 帧,该帧的帧长度为20,帧类型Type 为DATA(0),

帧标志Flags 为0x00,流标志符为1,HTTP/2 的有效包体数据信息,

也即是gRPC 数据信息为15 个字节(5 字节的gRPC 包头+15 字节的gRPC 包体内容(”I am datumhu“));c. 最后是一个终止流的HEADERS 帧,

该HEADERS 帧的帧长度为24,帧类型Type 为HEADS(1),帧标志Flags 为End Headers,End Stream(0x05),流标志符为1,

HEAD 长度为40 字节,head 数量为2,分别为grpc-status: 0、grpc-message:如下图所示:

8)客户端回复WINDOW_UPDATE 帧和PING 帧客户端收到服务端的DATA 响应后,给服务器发送一个WINDOW_UPDATE 帧和PING 帧,

其中WINDOW_UPDATE 的窗口大小增量为20(收到服务端响应的DATA 帧长度),如下图所示:

9)服务端回PING 帧最后服务器收到客户端的PING 帧后,回复一个PING 帧确认(ACK=1),如下图所示:

以上一次gRPC 调用的数据流图概括为如下:

总结本文首先概述了gRPC 的原理,由于gRPC 是基于HTTP/2 协议进行网络传输,随后简介了HTTP/2 通过多路复用和头部压缩等优化措施,基本解决了HTTP/1.x 包头阻塞的问题,

相对HTTP/1.1 带来了性能提升。HTTP/2 多路复用和头部压缩的关键在于HTTP/2 通过帧的设计优化了HTTP 协议语义。所以接着介绍了HTTP/2 的帧结构和gRPC 的协议。

最后通过抓包一次完整的gRPC 调用,分析了GRPC-HTTP2 的数据流过程,希望能够加深对gRPC 的理解。

标题:谷歌开源项目(google rpc框架)
链接:https://www.52hkw.com/news/rj/62736.html
版权:文章转载自网络,如有侵权,请联系删除!
资讯推荐
更多
Tiktok专用的梯子加速器(TK加速器全球加速)

Tiktok作为当前最火爆的短视频平台,受到了全球用户的热烈欢迎。然而,由于网络限制或者其他原因,很多用户在观看

2025-04-22
怎么不让快递放菜鸟驿站

菜鸟裹裹怎么禁止放快递?经常网购的小伙伴都知道,如果附近有菜鸟驿站,那么驿站的快递员会默认选择放在驿站中,并

2025-04-22
德国游戏排行榜前十名(德国出品的游戏)

中国的玩家可能在新闻里听过德国科隆游戏展,但对德国的游戏却感觉很陌生。游戏玩家大部分多少应该都体验过SL

2025-04-22
菜鸟驿站怎么送货上门

菜鸟裹裹怎么送货上门?有过菜鸟驿站拿快递的小伙伴都知道,很多菜鸟驿站在派送快递时,默认是放在菜鸟驿站,需要我

2025-04-22