浅析 HTTP/3

浅析 HTTP/3

Tags
开发
计算机网络基础
Description
互联网工程任务组 (IETF) 于 2022 年 6 月正式发布了 HTTP/3
Published
July 10, 2024
 

HTTP/3 简介

HTTP/3 的出现是为了解决一些历史问题的。
HTTP/1.1 和 HTTP/2 都是基于 TCP 协议的,TCP 协议是互联网使用最为广泛的协议之一,最早标准化于  RFC 793 (1981)
 
虽然 HTTP 期间迭代了几个版本,但是始终未能解决核心的问题
下面简单回顾下HTTP的几个版本
 

HTTP 回顾

HTTP/1.0

无状态无连接的应用层协议
  • 无状态:服务器不跟踪不记录请求过的状态
  • 无连接:浏览器每次请求都需要建立tcp连接
 
存在以下缺陷
  • 无法复用连接
    • 每次发送请求的时候,都需求进行一次 TCP 连接(三次握手),TCP连接释放(四次挥手)。网络利用率非常低。
  • 队头堵塞(head of line blocking)
    • 后面会展开讲,此处略过
       

HTTP/1.1

相比之前的 HTTP/1.0 版本,HTTP/1.1 做了很多改进和优化,使得网络通信更高效。
  • 长连接
    • 增加了一个 Connection 字段,通过设置 Keep-alive (默认设置)可以保持同域名下的连接不断开,避免每次客户端和服务器请求都需要重复建立和释放TCP链接,提高了网络的利用率。
      keep-alive 单个 TCP 连接在同一时刻只能处理一个请求
  • 支持请求的管道化(pipelining)提高吞吐性能
    • 管线化使得请求能够“并行”传输(P.s 此处非真正意义上的并行传输)。可以同时并行发送多个请求.
  • 缓存处理
    • 新的字段如cache-control,支持断点传输,以及增加了Host字段
       

HTTP/2.0

  • 二进制分帧
    • HTTP/2.0 采用 二进制格式 传输数据,而非 HTTP/1.x 的文本格式,二进制协议解析起来更高效
      HTTP/1.x 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。
      HTTP/2.0 将请求和响应数据分割为更小的帧,并且它们采用二进制编码
  • 多路复用
    • 同域名下的所有通信都在单个连接中完成。
    • 同个域名只需要占用一个TCP连接,消除了因多个TCP连接而带来的延时和内存消耗。
    • 单个连接上可以并行交错地请求和响应,之间互不干扰。
    • 单个连接可以承载任意数量的双向数据流。
    • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装 这一特性,使性能有了很大的提升
    • 在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。 可见,HTTP/2.0实现了真正的并行传输,它能够在一个TCP上进行任意数量HTTP请求。而这个强大的功能则是基于“二进制分帧”的特性。
  • 服务器推送
    • 服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
      服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。
  • 头部压缩
    • HTTP/2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。高效的压缩算法可以很大的压缩header,减少发送包的数量从而降低延迟。
       

      HTTP/1.x keep-alive 和 HTTP/2 多路复用的区别

      -
      HTTP/1.x keep-alive
      HTTP/2 多路复用
      传输方式
      基于文本,只能整体传输
      基于二进制流,可以流式发送
      响应顺序
      必须按照请求发送的顺序返回响应
      不按序响应
      -
      为解决队头阻塞,将同一个页面的资源分散到不同的域名下,开启多个TCP链接
      所有的通信在单个连接上完成
      -
      单个TCP同一时刻只能处理一个请求
      单个TCP同一时刻可以发送多个请求和响应
       

      TCP 的问题

      TCP队头拥塞

      notion image
      notion image
      notion image

      QUIC

      QUIC(Quick UDP Internet Connections)是一种通用、安全、多路复用的传输层新型网络协议。它的目的是替代TCP(目前是互联网上用于数据传输的主流协议)。2012年,QUIC协议由当时还在谷歌任职的Jim Roskind开发。2013年,QUIC正式对外公布。
      2015年,QUIC被提交给IETF进行标准化,但是直到六年以后,也就是2021年5月,IETF才发布了第一版标准化的QUIC,被命名为RFC 9000。同时,IETF还发布使用了QUIC的HTTP/3标准化版本。
      QUIC吸纳了很多与TCP类似的属性,还有TLS加密,将它们置于UDP传输之上的应用层中。

      HTTP/3

      HTTP/3终于标准化2022年6月6日,IETF QUIC和HTTP工作组成员Robin Mark在推特上宣布,历时5年,HTTP/3终于被标准化为 RFC 9114 ,这是HTTP超文本传输协议的第三个主要版本。同时, HTTP/2也被更新为新的RFC 9113。Robin写道,新发布的HTTP/3标准将与RFC 9204(QPACK header压缩) 和 RFC 9218(可扩展的优先级)一起为Web打开重要的新篇章。
      notion image
      为了改进http1.x的一些问题,http2引入了不少新特性;但由于历史沉积的原因,大量的IT基础设置都是基于TCP/IP协议存在的,短时间不可能颠覆式的更改;http2也只是在TCP协议之上做了封装,缓解了燃眉之急;然而http2无法跨越TCP传输拥塞的问题,某个TCP包的丢失,会导致后续包的重传并确认。
      理论上想要根本解决这个问题需要重新设计一套能取代TCP的协议,这太难了,一个IPV6协议现在都没有普及,因为不兼容。
      http2遗留的一些问题,比如TCP拥塞重传,在无线网大行其道的当下尤其突出。为了在兼容现有基础设施的基础上,解决这些问题,人类找到了一直被冷落的UDP协议,并在此基础上现实了很多TCP和http2的优秀特性,那就是QUIC协议,并最终提出了HTTP3标准。
      下图也能比较形象的反应HTTP家族间的异同:
      notion image
      基于QUIC协议的HTTP3
      从上图你可以看到 HTTP/3 有一个关键的改变,那就是它把下层的 TCP换成了 UDP。因为 UDP 是无序的,包之间没有依赖关系,所以就从根本上解决了“队头阻塞”。
      UDP 是一个简单、不可靠的传输协议,只是对 IP 协议的一层很薄的包装,和 TCP 相比,它实际应用的较少。
      不过正是因为它简单,不需要建连和断连,通信成本低,也就非常灵活、高效,“可塑性”很强。
      所以,QUIC 就选定了 UDP,在它之上把 TCP 的那一套连接管理、拥塞窗口、流量控制等“搬”了过来,“去其糟粕,取其精华”,打造出了一个全新的可靠传输协议。

      HTTP/3 的问题与挑战

    • UDP 连通性问题
      • 电信运营商对 UDP 数据包的”歧视”问题(UDP 泛洪Dos攻击)
        国内运营商对 UDP 的限流
    • QUIC 不支持明文传输
      • 利好用户。不利于国内的内容审查(也应该不是大问题)
    • UDP 资源消耗多
      • 当前阶段,UDP消耗的CPU资源多,且处理速度慢。
    • 国内的普及率并不高
    •  

      参考文章

    • 当我们在谈论HTTP队头阻塞时,我们在谈论什么?
    • HTTP3为什么抛弃了经典的TCP,转而拥抱 QUIC 呢
    •