云原生计算基金会(Cloud Native Computing Foundation,CNCF)是一个非盈利的开源组织,专注于推动云原生计算的发展和标准化。而gRPC(Google Remote Procedure Call)是由Google发起并开源的高性能、跨语言RPC框架。2017年,Google将gRPC项目捐赠给了CNCF,使其成为云原生生态的核心组件之一。gRPC与Kubernetes(容器编排)、Prometheus(监控)、Istio(服务网格)等CNCF项目深度集成,广泛应用于微服务架构和云原生应用中,其重要性随着云原生理念的普及而日益凸显。
gRPC巧妙地结合了ProtoBuf、HTTP/2等成熟技术,为上述RPC三大问题提供了全面且标准化的解决方案。
1)数据表示:默认采用 ProtoBuf作为其IDL和高效的二进制序列化方案。
2)数据传递:建立在 HTTP/2 协议之上,利用其多路复用、流控、头部压缩等特性实现高效网络通信。
3)方法约定:通过 ProtoBuf IDL (.proto 文件) 定义服务接口和消息结构。
HTTP/2协议
HTTP/2是HTTP/1.1的重大升级版,其设计源于Google的SPDY协议,并于2015年正式成为标准(RFC 7540)。HTTP/1.1虽应用广泛,但其固有的性能瓶颈------如队头阻塞(Head-of-Line Blocking)、较高的连接建立延迟、低效的文本头部传输------已难以满足现代Web应用对高性能、低延迟的需求。HTTP/2旨在克服这些问题,显著提升传输效率和用户体验。
与HTTP/1.1的纯文本传输不同,HTTP/2引入了二进制分帧层 (Binary Framing Layer)。所有HTTP消息(请求/响应)都被封装成一个个二进制编码的帧 (Frame) 进行传输。这种设计不仅提高了处理效率和健壮性(解析二进制比文本更快更不容易出错),还为多路复用(Multiplexing)、头部压缩(Header Compression)和服务器推送(Server Push)等高级特性奠定了基础。
HTTP/2的核心架构包含以下几个关键概念。
1)Connection(连接):一个TCP连接支持多个并发Stream,减少了HTTP/1.1中多个TCP连接的开销和延迟。
2)Stream(流):独立的双向通信通道,用于传输一条或多条Message,避免了队头阻塞。
3)Message(消息):对应HTTP/1.1的请求或响应,由一个或多个Frame组成,使数据传输更灵活。
4)Frame(帧):最小的通信单位,采用二进制格式,包含元数据和有效载荷,用于客户端与服务器间的信息传递。
帧结构
帧是一种长度前缀消息(Length-Prefixed-Message)。帧以固定的9字节作为帧头,后面跟着变长的帧载荷(Frame Payload),帧头包括如下公共字段:Type、Length、Flags, Stream Identifier。
c
+-----------------------------------------------+
| Length (24) |
+---------------+---------------+---------------+
| Type (8) | Flags (8) |
+-+-------------+---------------+-------------------------------+
|R| Stream Identifier (31) |
+=+=============================================================+
| Frame Payload (0...) ...
+---------------------------------------------------------------+
HTTP/2协议定义了10种不同类型的帧(Frame),其中通用格式包含以下几个关键类型,这些类型共同定义了帧的行为和内容。
1)Length(长度):表示帧载荷(Frame Payload)的长度,以字节为单位。其最大长度为2^14(即16384字节),不包括帧头的9个字节。
2)Type(类型):用于标识帧的类型。其中,DATA帧和HEADERS帧,分别对应于HTTP/1.1中的数据和头部信息。其他帧类型还包括SETTINGS、PRIORITY、RST_STREAM等,用于实现协议的各种高级特性。
3)Flags(标志):该字段包含一组标志位,用于传递帧的附加控制信息。常用的标志位包括: END_HEADERS:表示当前帧是头数据(Headers)的最后一帧,相当于HTTP/1.1中头信息结束后的空行("\r\n");END_STREAM:表示当前帧是流(Stream)中最后一个帧,标志着单方向数据传输的结束(End of Stream, EOS),相当于HTTP/1.1中分块传输编码(Chunked Encoding)的结束标志("0\r\n\r\n");PRIORITY:用于指示流的优先级,帮助服务器和客户端优化资源分配。
4)R(保留字段):该字段为保留位,目前未使用,必须设置为0。
5)Stream Identifier(流标识符):用于标识帧所属的流(Stream)。每个流都有一个唯一的标识符,用于在同一个TCP连接中区分不同的并发流。流标识符的长度为31位,其中客户端发起的流使用奇数标识符,服务器发起的流使用偶数标识符。
消息的语义兼容性
HTTP/2 协议与 HTTP/1尽可能保持兼容。从应用程序的角度来看,协议的功能基本没有变化。为了实现这一点,HTTP/1的所有请求和响应语义被保留,虽然传达那些语义的语法已经改变。
HTTP/1使用消息起始行(start-line)来传达目标 URI,请求方法和响应的状态代码,而HTTP/2为此使用以":"字符开头的特殊字段(pseudo-header)来达到相同的目的。
可以看到在第一个请求中,前两个头通常类似与HTTP/1。
bash
GET /resoure HTTP/1.1
Host: https://example.com
...
现在被拆分为一个标题框。
bash
:method: GET
:scheme: https
:host: example.com
:path: /resource
...
而其余的头则大致相同,都是lower-case字符。
HTTP/2尝试尽可能地最小化有效载荷大小。它将压缩与前一个请求中相同的头。在HTTP/1中,一个连续的请求看起来像是针对不同资源的初始请求。
bash
GET /otherResource HTTP/1.1
Host: https://example.org
...
而在HTTP/2中,对同一服务器的连续请求只需要:path头部信息。
bash
:path: /otherResource
因为所有其他头部信息都被标记并压缩缓存,并且可以通过"索引"进行还原。
未完待续
很高兴与你相遇!如果你喜欢本文内容,记得关注哦!