HTTP发展史
https://xiaolincoding.com/network/2_http/http3.html
HTTP1.0
比较朴素,典型模式是简历TCP,请求HTML,返回HTML,关闭TCP。网页有几十上百个资源的时候,需要反复简历TCP连接。TCP本身就是有成本的。连接利用率低。
HTTP1.1
http1.1最大的改进是支持keep-alive。一个TCP可以用来请求多个内容,因此不需要每个HTTP请求都重新进行TCP三次握手。
此外 HTTP/1.1 还加入/完善了很多机制,比如:
- Persistent Connection 长连接
- Pipeline 管线化
- Host 请求头
- Cache-Control、ETag 等缓存机制
- Transfer-Encoding: chunked 分块传输
- Range 范围请求
- 更多状态码
但是同一个TCP连接上的处理效率仍然有限。
虽然设计过HTTP pipelineing,但服务器还是要按照请求顺序返回响应
Request A
Request B
Request C
↓
Response A
Response B
Response C假设A特别慢,B和C准备好了也可能被A挡住。
这就是HTTP1.1层面的队头阻塞。因此浏览器会通过简历多个TCP连接来绕过这个问题。
HTTP2
HTTP2最重要的变化是多路复用 multiplexing。HTTP/2不再简单把HTTP消息作为连续文本发送,而是转换成
HTTP Message
↓
Frame
Frame
Frame也就是二进制分帧。不同请求都帧可以交错传输。接收端根据stream ID再重新组装。
所以多个和请求可以使用一个TCP连接,同时进行。
HTTP2的另外一个主要优化是HPACK头部压缩。Http1.1每次要发送大量重复的Header。
HTTP2会维护Header table。后续很多内容只需要发送索引或增量信息,从而降低Header开销。
另外HTTP2还引入了。
- 二进制分帧
- Stream 流
- 多路复用
- HPACK Header 压缩
- Stream Priority
- Server Push
其中 Server Push 后来实际使用并不理想,现在浏览器基本已经放弃它,所以面试里知道它是 HTTP/2 的设计特性即可。
HTTP 3
HTTP3在2022年六月发布了,使用QUIC协议。
HTTP2是多个请求跑在一个TCP连接中的,那么当TCP丢包时,整个TCP都要等待重传,那么就会阻塞该TCP连接中的所有请求。即使收到了后续的TCP报文,应用层也是无法读取的。这是因为TCP层必须保证收到的字节是完整有序的,如果序列号较低的TCP段子网络中丢失了,即使较高的TCP段已经被接受了,应用层也无法读取到这部分数据。从HTTP视角来看,请求被堵塞了。
此外TCP的TLS握手需要3个RTT(TLS1.3只需要1+1),由于TCP具有拥塞控制的特性,所以刚建立的TCP会有蛮启动的过程,它会对TCP连接产生减速效果。
TCP连接是四元组,如果IP地址或端口变了,就会导致需要TCP和TLS重新握手,这不利于移动设备切换网络的场景。比如4G网络切换为wifi。
QUIC
UDP是一个简单不可靠的传输协议,包之间是无序的,也没有依赖关系。UDP在应用层实现了QUIC协议,它具有类似TCP的连接管理,拥塞窗口、流量控制等特性,相对于将不可靠的UDP协议变成可靠的了。所以不用担心数据丢失的问题。
- 无队头阻塞
- 更快的连接简历
- 连接迁移

QUIC也有HTTP2流式多路复用,也就是在同一条连接上并发传输多个stream。
在HTTP2中一个HTTP请求对应一个stream响应也在同一个stream上返回。
在HTTP3中一个HTTP请求对应一个QUIC stream。请求和对应响应都走这个stream。
QUIC协议会保证数据包的可靠性,每个数据包都有一个序号唯一标识。当某个流中的一个数据包丢失,即使该流的其他数据包到达 了,数据也无法被HTTP3读取,直到QUIC重传丢失报文,数据才会交给HTTP3
QUIC连接上的多个Stream之间没有依赖,都是独立的,某个流发还是能丢包了,只会响应该流,其他流不受影响。
QUIC只需要一次握手。就可以建立TLS连接,HTTP3当会话恢复时,有效负载数据与第一个数据包一起发送,可以做到0RTT。
QUIC没有通过四元组的方式来绑定连接,而是通过连接ID来标记通信的俩个客户端,客户端和服务端各选一个ID标记自己,因此即使设备的网络变化后,导致IP地址变了,只要保有上下文信息,就可以无缝使用之前的连接,消除重新连接的成本。达到了连接迁移到功能。
QUIC不只是HTTP3的底层协议。
HTTP/3:这是 QUIC 最大规模的实际应用。浏览器、CDN、Google、Cloudflare 等大量使用。
DNS over QUIC(DoQ):DNS 查询直接跑在 QUIC 上,相比传统 DoT/TCP 可以减少连接建立开销,同时具备加密和多路复用能力。
WebTransport:给 Web 应用提供比 WebSocket 更灵活的双向通信能力,可以同时使用可靠流和不可靠 Datagram。其 HTTP/3 版本本质上利用了 QUIC 的 stream/datagram 能力。
代理 / VPN 类协议(MASQUE):这是 QUIC 一个很重要的新应用方向。MASQUE 可以通过 HTTP/3/QUIC 隧道转发 UDP、IP 等流量,用于 VPN、隐私代理、移动网络中继等。IETF 到 2026 年仍然在积极推进这套协议,例如 QUIC-aware proxy 和 UDP proxy 扩展。
WebRTC 等实时通信的代理传输:QUIC 不等于 WebRTC 的默认媒体传输协议,但 MASQUE 正在扩展 UDP 代理能力来覆盖 WebRTC 这样的 P2P UDP 场景。2026 年 8 月,相关的 “Proxying Bound UDP in HTTP” 已获 IESG 批准为 Proposed Standard。
自定义应用协议:游戏、RPC、实时数据同步等都可以直接建立在 QUIC 上,不一定非得套 HTTP。QUIC 原生提供多路复用 stream、可靠传输、流控、拥塞控制、TLS 1.3 加密以及连接迁移,这些对于移动端尤其有价值。
但是目前在内网中,TCP仍然是一个更好的选择。
JS等语言为了性能,会把QUIC的流控,丢包恢复交给其他语言实现。
node:quic底层是C++,@currentspace/http3底层是rust。
python的aioquic底层QUIC是python来实现的,但是TLS部分交给了C++
java的netty http3,QUIC是在native quiche完成,而不是java自己完全写一遍。Kwik 则是把这部分放在了java中。java中国使用quiche不是因为性能不行,而是QUIC非常复杂。重写一套成熟,安全,的QUIC栈成本非常高。
go语言中的quic-go是纯go实现的。