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协议层面的总结。两个协议没有好坏,关键在于你的场景选对。