gRPC 笔记(06)— gRPC 的 HTTP2 实现流程、简单RPC模式、服务器端RPC模式、客户端RPC模式、双向RPC模式的消息流传递

gRPC 使用 HTTP/2 作为其传输协议,实现通过网络发送消息。这也是 gRPC 能够成为高性能 RPC 框架的原因之一。

HTTP/2 中,客户端和服务器端的所有通信都是通过一个 TCP 连接完成的,这个连接可以传送任意数量的双向字节流。

相关术语如下:

  • 流(stream):在一个已建立的连接上的双向字节流。一个流可以携带一条或多条消息。
  • 帧(frame):HTTP/2 中最小的通信单元。每一帧都包含一个帧头,它至少要标记该帧所属的流。
  • 消息(message):完整的帧序列,映射为一条逻辑上的 HTTP 消息,由一帧或多帧组成。这样的话,允许消息进行多路复 用,客户端和服务器端能够将消息分解成独立的帧,交叉发送 它们,然后在另一端进行重新组合。

如图所示,gRPC 通道代表一个到端点的连接,也就是一个 HTTP/2 连接。当客户端应用程序创建 gRPC 通道的时候,它会在幕后创建一个到服务器端的 HTTP/2 连接。在通道创建完成之后,就可以重用它来发送多个到服务器端的远程调用。这些远程调用会映射为 HTTP/2 中的 流。远程调用中的消息以 HTTP/2 帧的形式进行发送,帧可能会携带一 条 gRPC 长度前缀的消息,也可能在 gRPC 消息非常大的情况下,一条消息跨多帧。

gRPC与HTTP2关系

1. 请求消息

请求消息用于初始化远程调用。在 gRPC 中,请求消息始终由客户端应用程序来触发,它包含 3 部分:

  • 请求头信息
  • 以长度作为前缀的消息
  • 流结束标记(end of stream flag,以下简称 EOS 标记),

如图所示。远程调用在客户端发送请求头信息之后就会初始化,然后其中会发送以长度作为前缀的消息,最后发送 EOS 标记,通知收件方请求消息已发送。

请求消息中的元素序列
当调用 getProduct 方法时,客户端会通过发送下面的请求头信息来初始化调用。

HEADERS (flags = END_HEADERS) 
:method = POST ➊ 
:scheme = http ➋ 
:path = /ProductInfo/getProduct ➌ 
:authority = abc.com ➍ 
te = trailers ➎ 
grpc-timeout = 1S ➏ 
content-type = application/grpc ➐ 
grpc-encoding = gzip ➑ 
authorization = Bearer xxxxxx ➒
  • ❶ 定义 HTTP 方法。对 gRPC 来说,:method 头信息始终为 POST
  • ❷ 定义 HTTP 模式。如果启用传输层安全协议(Transport Level Security,TLS),就将模式设置为 https,否则设置为 http
  • ❸ 定义端点路径。对 gRPC 来说,这个值的构造为 /{ 服务名 }/{ 方 法名 }
  • ❹ 定义目标 URI 的虚拟主机名。
  • ❺ 定义对不兼容代理的检测。在 gRPC 中,这个值必须为 trailers
  • ❻ 定义调用的超时时间。如果没有指定,服务器端会假定超时时间无 穷大。
  • ❼ 定义 content-type。对 gRPC 来说,content-type 应该以 application/grpc 开头。否则,gRPC 会给出 HTTP 状态为 415(不 支持的媒体类型)的响应。
  • ❽ 定义消息的压缩类型。可选的值是 identitygzipdeflatesnappy{custom}
  • ❾ 这是可选的元数据。authorization 元数据用来访问安全的端点。

其它注意点:

  • 名称以 : 开头的头信息叫作保留头信息,HTTP/2 要求保留头信息出现在其他头信息之前。
  • gRPC 通信中所传递的头信息分为两类:调用定义的头信息 (call-definition header)和自定义元数据。
  • 调用定义的头信息是 HTTP/2 预定义的头信息。这些头信息应该在自定义元数据之前发送。
  • 自定义元数据是由应用程序层定义的任意一组键–值对。在声明自定义元数据时,需要确保不要使用以 grpc- 开头的名称。在 gRPC 核心中,这被列为保留名字。

当完成对服务器端调用的初始化之后,客户端会以 HTTP/2 数据帧的形式发送以长度作为前缀的消息。如果这条消息不适合放到一个数据帧中,那么它可以跨多个数据帧。请求消息的结束通过在最后一个 DATA 帧上添加 END_STREAM 标记来实现。当因为没有要发送的数据而需要关闭请求流时,必须发送一个带有 END_STREAM 标记的空数据帧:

DATA (flags = END_STREAM) 
<Length-Prefixed Message>

2. 响应消息

响应消息由服务器端生成,用来响应客户端的请求。与请求消息类似, 在大多数场景中,响应消息也包含 3 个主要部分:响应头信息、以长度作为前缀的消息以及 trailer。如果没有发送以长度作为前缀的消息来响应客户端,则响应消息只会包含头信息和 trailer,如图所示:
响应消息
下面通过同一个示例来介绍响应消息的 HTTP/2 帧序列。当服务器端发送响应消息至客户端时,首先会发送如下所示的响应头信息。

HEADERS (flags = END_HEADERS) 
:status = 200 ➊ 
grpc-encoding = gzip ➋ 
content-type = application/grpc ➌
  • ❶ 表明 HTTP 请求的状态。
  • ❷ 定义消息的压缩类型。可选的值是 identitygzipdeflatesnappy{custom}
  • ❸ 定义 content-type。对 gRPC 来说,content-type 应该以 application/grpc 开头。

与请求头信息类似,应用程序层所定义的自定义元数据也可以按照任意键–值对集的形式在响应头信息中进行发送。

服务器端发送完响应头之后,以长度作为前缀的消息就会以 HTTP/2 数据帧的形式在调用中进行发送。与请求消息类似,如果该消息不适合放到一个数据帧中,那么它可以跨多个数据帧。

DATA 
<Length-Prefixed Message>

如下所示,END_STREAM 标记并不会随数据帧一起发送,而会作为单独的头信息来发送,名为 trailer,最后,通过发送 trailer 来提醒客户端响应消息已发送。trailer 还会携带状态码以及请求的状态信息。

HEADERS (flags = END_STREAM, END_HEADERS) 
grpc-status = 0 # OK ➊ 
grpc-message = xxxxxx ➋
  • ❶ 定义 gRPC 状态码。gRPC 会使用一组定义良好的状态码。这些状态码的定义可以在 gRPC 官方文档中找到。
  • ❷ 定义对错误的描述。这是可选的,只有在处理请求出现错误时,才会进行设置。

trailer 会以 HTTP/2 头信息帧的形式进行投递,但会在响应消息结束时发送。响应 EOS 标记就是在 trailer 头信息中设置的 END_STREAM 标记。另外,它还会包含 grpc-status 头信息和 grpc-message 头信息。

在特定的场景中,请求调用可能会立即失败。在这些情况下,服务器端需要发回一个不包含数据帧的响应。因为服务器端只发送 trailer 作为响应,所以这些 trailer 也会以 HTTP/2 头信息帧的形式进行投递,同时会包含 END_STREAM 标记。另外,trailer 会包含下面的头信息。

  • HTTP 状态:status
  • 内容类型:content-type
  • 状态:grpc-status
  • 状态信息:grpc-message

3. gRPC 通信模式中的消息流

3.1 简单 RPC 模式

在一元 RPC 模式中,gRPC 服务器端和 gRPC 客户端的通信始终只涉及一个请求和一个响应。如图 所示,请求消息包含头信息, 随后是以长度作为前缀的消息,该消息可以跨一个或多个数据帧。 消息最后会添加一个 EOS 标记,方便客户端半关(half-close)连 接,并标记请求消息的结束。在这里,“半关”指的是客户端在自己的一侧关闭连接,这样一来,客户端无法再向服务器端发送消息, 但仍能够监听来自服务器端的消息。只有在接收到完整的消息之后,服务器端才生成响应。响应消息包含一个头信息帧,随后是以长度作为前缀的消息。当服务器端发送带有状态详情的 trailer 头信息之后,通信就会关闭。
简单RPC消息流

3.2 服务器端 RPC 模式

从客户端的角度来说,一元 RPC 模式和服务器端流 RPC 模式具有相同的请求信息流。这两种情况都是发送一条请求消息,主要差异在于服务器端。

在服务器端流 RPC 模式中,服务器端不再向客户端发送一条响应消息,而会发送多条响应消息。服务器端会持续等待,直到接收到完整的请求消息,随后它会发送响应头消息和多条以长度作为前缀的消息,如图所示。在服务器端发送带有状态详情的 trailer 头信息之后,通信就会关闭。

服务器端RPC模式

3.3 客户端 RPC 模式

在客户端流 RPC 模式中,客户端向服务器端发送多条消息,服务器端在响应时发送一条消息。

客户端首先通过发送头信息帧来与服务器端建立连接,然后以数据帧的形式,向服务器端发送多条以长度作为前缀的消息,如图所示。最后,通过在末尾的数据帧中发送 EOS 标记,客户端将连接设置为半关的状态。与此同时, 服务器端读取所接收到的来自客户端的消息。在接收到所有的消息之后,客户端发送一条响应消息和 trailer 头信息,并关闭连接。

客户端gRPC 模式

3.4 双向流 RPC 模式

在这种模式中,客户端和服务器端都会给对方发送多条消息,直到它们关闭连接为止。

在双向流 RPC 模式中,客户端通过发送头信息帧与服务器端建立连接。然后,它们会互发以长度作为前缀的消息,无须等待对方结 束。如图所示,客户端和服务器端会同时发送消息。两者都可以在自己的一侧关闭连接,这意味着它们不能再发送消息了。
双向gRPC模式
参考:《gRPC与云原生应用开发》

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值