27 HTTP/3
一篇写得很细的博文:HTTP3.0和QUIC协议那些事
-
总结
1、HTTP/3 基于 QUIC 协议,完全解决了队头阻塞 问题(不使用 TCP,改为 UDP),弱网环境下的表现会优于 HTTP/2
2、QUIC 是一个新的 传输层协议,建立在 UDP 之上,实现了可靠传输
3、QUIC 内含了 TLS1.3,只能加密通信,支持 0-RTT 快速建连
4、QUIC 的连接使用不透明的连接 ID,不绑定在 IP 地址 + 端口 上,支持连接迁移
5、QUIC 的流与 HTTP/2 的流很相似,但 分为双向流和单向流
6、HTTP/3 没有指定默认端口号,需要用 HTTP/2 的 扩展帧Alt-Svc 来发现
为什么说HTTP2 没有完全解决队头堵塞呢?
HTTP/2 虽然使用帧、流、多路复用,(在应用层)没有了队头阻塞,但这些手段都是在 应用层 里,而在下层传输层的 TCP 协议 里,还是会发生队头阻塞
-
队头阻塞的解决方案
- HTTP/1.1 存在 HTTP 层和 TCP 层两个层次的队头阻塞
- HTTP/2 - 多路复用机制 解决了 HTTP 层(应用层)的队头阻塞,TCP 层仍存在
-
TCP队头堵塞 - TCP拥塞控制的四个算法:慢启动,拥塞避免,快速重传,快速恢复
当 HTTP/2 把多个 请求 - 响应 分解成流,交给 TCP 后,TCP 会再拆成更小的包
segment
依次发送队头堵塞:TCP 为了保证可靠传输,有个特别的 丢包重传 机制,丢失的包必须要 等待重新传输确认,其他的包即使已经收到了,也只能放在缓冲区里,上层的应用拿不出来,只能干着急【一个数据包影响了一堆数据包,它不来大家都走不了】
HTTP/3 – HTTP over QUIC
QUIC - 传输层协议(和TCP平级)
HTTP/3 将 TCP 更换为 UDP – 因为 UDP 是 无序的,包之间没有依赖关系,所以就从根本上解决了队头阻塞
着重对比下 HTTP/2 和 HTTP/3如下:
QUIC 协议特点
1、QUIC 基于 UDP,而 UDP 是 无连接 的,根本就不需要 握手和挥手,所以天生就要比 TCP 快
2、引入了类似 HTTP/2 的 流 和 多路复用,单个 流 是有序的,可能会因为丢包而阻塞,但其他 流 不会受到影响
QUIC 一个连接上的多个 stream 之间没有依赖。这样假如 stream2 丢了一个 udp packet,也只会影响 stream2 的处理。不会影响 stream2 之前及之后的 stream 的处理
3、QUIC 直接应用了 TLS1.3,获得了 0-RTT、1-RTT 连接的好处
QUIC协议可以实现在第一个包就可以包含有效的应用数据,从而实现0RTT
(前提条件:非首次传输)
4、QUIC 全面采用加密通信,可以很好地抵御窜改和协议僵化
5、QUIC 并不是建立在 TLS 之上,而是内部 包含了 TLS。它使用自己的帧 接管 了 TLS 里的 记录,握手消息、警报消息都不使用 TLS 记录,直接封装成 QUIC 的帧发送,省掉了一次开销
QUIC 内部细节
-
QUIC 的基本数据传输单位是包(
packet
)和帧(frame
),一个包由多个帧组成,包面向的是连接,帧面向的是流 -
QUIC 使用 不透明的连接 ID 来标记通信的两个端点,客户端和服务器可以自行选择一组 ID 来标记自己,这样就 解除了 TCP 里连接对IP 地址 + 端口 的强绑定,支持 连接迁移
举例:手机会自动由 4G 切换到 WiFi –> 这时 IP 地址会发生变化,TCP 就必须重新建立连接;而 QUIC 连接里的两端连接 ID 不会变,所以连接在“逻辑上”没有中断,它就可以在新的 IP 地址上继续使用之前的连接,消除重连的成本,实现连接的无缝迁移
-
解析结构细节:
1、帧类型
PING、ACK 等帧用于管理连接,而 STREAM 帧专门用来实现流
2、流标识符
HTTP/2 里的流都是双向的,而 QUIC 则分为双向流和单向流
流 ID 还保留了最低两位用作标志,第 1 位标记流的发起者,0 -客户端,1 - 服务器;第 2 位标记流的方向,0 - 双向流,1 - 单向流。
HTTP/3 协议
因为 QUIC 本身就已经支持了加密、流和多路复用,所以 HTTP/3 把 流控制 都交给 QUIC 去做。
-
流控制
调用的不再是 TLS 的安全接口,也不是 Socket API,而是专门的 QUIC 函数
-
HTTP/3 的帧结构
帧头:只有两个字段 类型和长度,最小只需要两个字节
-
头部压缩算法
升级成了
QPACK
,在流上发送HEADERS
帧时 不能更新字段,只能引用,索引表的更新需要在 专门的单向流 上发送指令来管理,解决了 HPACK 的队头阻塞问题 -
HTTP/3 服务发现 - 利用HTTP/2 里的扩展帧
–> 浏览器需要先用 HTTP/2 协议连接服务器
–> 服务器可以在启动 HTTP/2 连接后发送一个
Alt-Svc
帧,包含一个h3=host:port
的字符串,告诉浏览器在另一个端点上提供等价的 HTTP/3 服务–> 浏览器收到
Alt-Svc
帧,会使用 QUIC 异步连接指定的端口,如果连接成功,就会断开 HTTP/2 连接,改用新的 HTTP/3 收发数据