通常,消息分帧(message-framing)会构建消息和通信,以便于目标受众很容易地提取信息。对 gRPC 通信来说,情况同样如此。一旦获取了要发送给另一方的已编码数据,就需要以对方易于提取信息的方式打包数据。为了打包要通过网络发送的信息,gRPC 使用了名为长度前缀分帧(length-prefix framing)的消息分帧技术。
长度前缀分帧是指在写入消息本身之前,写入长度信息,来表明每条消息的大小。如图 4-4 所示,已编码的二进制消息前面分配了 4 字节来指明消息的大小。在 gRPC 通信中,每条消息都有额外的 4 字节用来设置其大小。消息大小是一个有限的数字,为其分配 4 字节来表示消息的大小,也就意味着 gRPC 通信可以处理大小不超过 4GB 的所有消息。
如图 4-4 所示,当消息使用 protocol buffers 编码时,我们会得到二进制格式的消息。然后,计算二进制内容的大小,并以大端(big-endian)格式将其添加到二进制内容的前面。
大端是一种在系统或消息中对二进制数据进行排序的方式。在大端格式中,序列中的最高有效位(2 的最大乘方)存储在最低的存储地址上。
除了消息的大小,帧中还有单字节的无符号整数,用来表明数据是否进行了压缩。假设压缩标记值为 1,这代表二进制数据使用 MessageEncoding 头信息中声明的机制进行了压缩,该信息会作为 HTTP 传输头信息中的一项。假设值为 0,则代表消息字节没有进行压缩。4.4 节将详细讨论 gRPC 通信所支持的 HTTP 头信息。
现在,消息已经分帧完成,可以通过网络将其发送给收件方了。对于客户端的请求消息,收件方是服务器;而对于响应消息,收件方则是客户端。在收件方一侧,当收到消息之后,首先要读取其第一字节,来检查该消息是否经过压缩。然后,收件方读取接下来的 4 字节,以获取编码二进制消息的大小,接着就可以从流中精确地读取确切长度的字节了。
对于简单的消息,只需处理一条以长度为前缀的消息;而对于流消息,就会有多条以长度为前缀的消息要处理。
我们大致理解了如何准备消息,以便于通过网络发送给收件方。4.4 节将讨论 gRPC 如何通过网络发送这些以长度为前缀的消息。目前,gRPC 核心支持 3 种传输实现:HTTP/2、Cronet 和进程内(inprocess)。在这 3 种实现中,最常见的是 HTTP/2。下面看一下 gRPC如何利用 HTTP/2 网络高效发送消息。