2. HTTP/1.1 vs HTTP/2:协议基础归纳

很多人问我,选RESTful还是gRPC,第一步看什么?

我一般会反问:你先搞清楚HTTP/1.1和HTTP/2的区别了吗?

说白了,这两个协议虽然都叫HTTP,但骨子里的差异巨大。gRPC能跑在HTTP/2上,这不是巧合,是被设计出来的。今天我们就好好掰扯一下这两者的核心差别。

2.1 连接复用能力

这是最直观的区别。HTTP/1.1有个老毛病——队头阻塞(Head-of-Line Blocking)。

核心差异: HTTP/1.1同一连接上只能串行处理请求,HTTP/2支持多路复用,一个连接可以并行处理多个请求。

我在项目中遇到过一个真实的性能瓶颈:前端页面加载几十个静态资源,HTTP/1.1的浏览器为了加速,会打开6个并发连接(这是浏览器的典型限制)。但仍然不够。每个连接上还有队头阻塞的问题——请求A没返回,请求B就得等着。

HTTP/2是怎么解决的?它引入了一个叫"二进制分帧层"的东西。

  • 流(Stream): 每个请求/响应是一个流,有唯一ID
  • 帧(Frame): 数据被拆成帧,帧可以在流的任意顺序中传输
  • 多路复用: 不同流的帧可以交错发送,互不阻塞

你想想看,如果我们要在一条水管里同时运输苹果和橙子,HTTP/1.1的方式是把苹果全运完再运橙子。HTTP/2呢?把苹果和橙子都切成小块,交替着运。速度快太多了。

2.2 头部压缩机制

这个点容易被忽略,但实际影响很大。HTTP/1.1的头部是纯文本的,每次请求都得带着完整的Header。

举个例子,一个Cookie可能就有几百字节,每次请求都原样发一遍。我做过一次统计:某个RESTful API,平均每个请求的头部占了总传输量的30%以上。

HTTP/2用了HPACK压缩算法,专门对付这个问题。

// HTTP/1.1 原始头部(纯文本)
GET /api/users HTTP/1.1
Host: example.com
Cookie: session_id=abc123; user_=xyz789
Accept: application/json
User-Agent: Mozilla/5.0

// HTTP/2 经过HPACK压缩后
// 静态表和动态表共同工作,重复的头部只传索引号
// 比如 :method: GET 已经在静态表中,只需传1个字节
对比项 HTTP/1.1 HTTP/2
头部格式 纯文本 压缩二进制
压缩算法 无 HPACK
重复头部开销 每次都完整发送 静态/动态表索引引用
头部节省比例 0% 通常50%-90%

经验之谈: 如果你的API请求频繁且头部信息又多(比如OAuth2的Bearer 、自定义Trace ID),用HTTP/2能节省大量带宽。我曾经把一个服务的流量从HTTP/1.1迁移到HTTP/2,仅头部压缩就让数据量减少了70%。

2.3 服务器推送

这个功能很多人听说过,但用得不多。服务器推送允许服务端在客户端请求之前,主动把资源发过去。

场景是这样的:浏览器请求一个HTML页面,服务器知道这个页面会引用style.css和app.js。HTTP/1.1得等浏览器解析HTML后发现这些依赖,再发起请求。HTTP/2可以在返回HTML的同时,主动把css和js一起推过去。

注意: 服务器推送不是银弹。滥用它会浪费带宽,尤其当客户端缓存了资源时,服务器还在傻傻地推送。我个人建议在gRPC中使用服务器推送的场景谨慎评估,不要为了用而用。

2.4 协议格式对比

HTTP/1.1是纯文本协议,你可以直接用telnet连上去敲请求。调试很方便,但解析效率低。

HTTP/2是二进制协议,数据以帧为单位传输。解析快,但调试麻烦,不能直接看文本。

// HTTP/1.1 文本协议示例(人类可读)
GET /api/users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer token123

// HTTP/2 二进制帧结构(机器可读)
+-----------------------------------------------+
| Length (24 bits)   | Type (8 bits)            |
+-------------------+---------------------------+
| Flags (8 bits)    | Reserved (1 bit)          |
+-------------------+---------------------------+
| Stream Identifier (31 bits)                   |
+-----------------------------------------------+
| Frame Payload (可变长度)                       |
+-----------------------------------------------+

我刚开始接触HTTP/2时也觉得二进制协议神秘,其实核心就三个字段:长度、类型、流ID。每个帧要么是HEADERS帧(头部),要么是DATA帧(数据),通过流ID关联到具体的请求。

2.5 对微服务架构的影响

讲这么多协议细节,最终要落到选型上。在你设计微服务间的通信时,这些差异会直接决定你的服务性能。

  • 连接数: HTTP/1.1下,N个服务之间可能需要N*N*6个连接(每个客户端6个连接),HTTP/2可以把连接数降到N*N
  • 延迟敏感度: 高频RPC调用下,HTTP/2的多路复用能显著降低延迟
  • 流式通信: gRPC基于HTTP/2的流式能力,可以实现服务端流、客户端流、双向流。HTTP/1.1做这个很费劲
  • 双向认证: 两者都支持TLS,但HTTP/2强制要求TLS(实际部署中)

我的建议: 如果服务间调用是短连接、请求量少,HTTP/1.1+JSON完全够用。但如果你是高频调用、需要流式处理或者追求极致的资源利用率,那就该考虑HTTP/2了。gRPC默认就是HTTP/2,这就是为什么它在微服务体系中这么受欢迎。

好,以上就是我对HTTP/1.1和HTTP/2协议层面的总结。两个协议没有好坏,关键在于你的场景选对。

HTTP/1.1 vs HTTP/2 对比全景图 HTTP/1.1 队头阻塞 同一连接请求串行处理 纯文本头部 每次请求完整传输Header 连接数爆炸 每个域通常6个并发连接 不支持服务器推送 vs 对比 HTTP/2 多路复用 单一连接并行处理多请求 HPACK头部压缩 二进制格式,索引表引用 连接复用 单一连接足够所有请求 支持服务器推送 gRPC 强制基于 HTTP/2,充分利用了多路复用、头部压缩和流式传输的优势