+-
看完 HTTP 协议的艰辛发家史,我悟到了......

今天一起来研究 HTTP 协议的一些事情,通过本文你将了解到以下内容:


  • HTTP 协议各版本的对比和优缺点;
  • HTTP/2.0 协议相关的 SPDY 协议、二进制分帧协议、多路复用、首部压缩、服务推送等基本原理;
  • HTTP/3.0 和 QUIC 协议。

  • 1 HTTP 协议各版本的对比


    HTTP 超文本传输协议同空气一般,感触不到它的存在但是又无处不在。笔者从维基百科摘录了一些 HTTP 协议的发展历程的简单信息,一起来看下吧。


    超文本传输协议是分布式协作超媒体信息系统的应用协议。超文本传输协议是万维网数据通信的基础,在万维网中超文本文档包括到用户可以轻松访问的其他资源的超链接。


    蒂姆·伯纳斯·李于 1989 年在欧洲核子研究中心发起了超文本传输协议的开发。早期的超文本传输协议征求意见(RFC)的开发是由互联网工程任务组(IETF)和万维网联盟(W3C)共同努力的结果,其工作后来转移到 IETF。


    万维网之父——蒂姆·伯纳斯·李简介


    Tim Berners-Lee 是英国工程师和计算机科学家,最著名的是万维网的发明者。他是牛津大学计算机科学教授和麻省理工学院教授。


    他于 1989 年 3 月 12 日提出了一种信息管理系统,然后在同年 11 月中旬通过 Internet 实现了超文本传输协议 HTTP 客户端和服务器之间的首次成功通信。


    他是万维网联盟 W3C 的负责人,该联盟负责监督 Web 的持续发展,他还是万维网基金会的创始人,还是麻省理工学院计算机科学和人工智能实验室 CSAIL 的 3Com 创始人主席和高级研究员,他也是网络科学研究计划 WSRI 的主任和 MIT 集体智慧中心的顾问委员会成员,他也是开放数据研究所的创始人兼总裁,目前是社交网络 MeWe 的顾问。


    2004 年,伯纳斯·李因其开创性工作而被女王伊丽莎白二世封为爵士。在 2009 年 4 月,他当选为美国国家科学院外籍研究员,位列《时代》杂志的 20 世纪 100 位最重要人物名单被誉为“万维网发明者”获得了 2016 年图灵奖。



    HTTP 各版本基本情况


    HTTP 协议经过 20 多年的演进出现过 0.9、1.0、1.1、2.0、3.0 五个主要版本,笔者画了张图看下:



    1.1 HTTP/0.9


    0.9 是鼻祖版本,它的主要特点包括:


  • 请求方法支持有限:只支持 GET 请求方式,不支持其他请求方式。因此客户端向服务端传输信息的量非常有限,也就是现在常用的 POST 请求无法使用;

  • 不支持请求头 Header:不能在请求中指定版本号,服务端只具有返回 HTML 字符串的能力;

  • 响应即关闭:服务端相响应之后,立即关闭 TCP 连接。


  • 1.2 HTTP/1.0

    1.0 版本主要是对 0.9 版本的强化,效果也比较明显,主要特性和缺点包括:


  • 丰富请求方法:请求方式新增了 POST、DELETE、PUT、HEADER 等方式,提高了客户端向服务端发送信息的量级;

  • 增加请求头和响应头:增添了请求头和响应头的概念。可以在通信中指定了 HTTP 协议版本号,以及其他 Header 信息,使得 C/S 交互更加灵活方便;

  • 丰富数据传输内容:扩充了传输内容格式,包括图片、音视频资源、二进制等都可以进行传输。相比 0.9 的只能传输 HTML 内容让 HTTP 的应用场景更多;

  • 链接复用性差:1.0 版本中每个 TCP 连接只能发送一个请求,数据发送完毕连接就关闭。如果还要请求其他资源,就必须重新建立连接。TCP 为了保证正确性和可靠性需要客户端和服务器三次握手和四次挥手,因此建立连接成本很高。基于拥塞控制开始时发送速率较慢,所以 1.0 版本的性能并不理想;

  • 无状态无连接的弊端:1.0 版本是无状态且无连接的,换句话说就是服务器不跟踪不记录请求过的状态,客户端每次请求都需要建立 TCP 连接不能复用。而且 1.0 规定在前一个请求响应到达之后下一个请求才能发送,如果前一个阻塞后面的请求就会被阻塞。 丢包和乱序问题和高成本的链接过程让复用和队头阻塞产生很多问题,所以无连接无状态是 1.0 版本的一个弱肋。


  • 1.3 HTTP/1.1


    1.1 版本在 1.0 版本发布后大约 1 年就推出了,是对 1.0 版本的优化和完善。1.1 版本的主要特点包括:


  • 增加长连接:新增 Connection 字段,可以设置 Keep-Alive 值保持连接不断开,即 TCP 连接默认不关闭,可以被多个请求复用。这也是 1.1 版本很重要的优化,但是在S端服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着,仍然存在队头阻塞问题;

  • 管道化:在长连接的基础上,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回。即在同一个 TCP 连接中,客户端可以同时发送多个请求,进一步改进了 HTTP 协议的传输效率;

  • 更多的请求方法:增加了 PUT、PATCH、OPTIONS、DELETE 等请求方式;

  • Host 字段:Host 字段用来指定服务器的域名,这样就可以将多种请求发往同一台服务器上的不同网站,提高了机器的复用,这个也是重要的优化。


  • 1.4 HTTP/2.0


    2.0 版本是个里程碑式的版本。相比 1.x 版本有了非常多的优化去适应当前的网络场景,下面是其中几个重要的功能点:


  • 二进制格式 :1.x 是文本协议,然而 2.0 是以二进制帧为基本单位,可以说是一个二进制协议。将所有传输的信息分割为消息和帧,并采用二进制格式的编码。一帧中包含数据和标识符,使得网络传输变得高效而灵活;
  • 多路复用 :这是一个非常重要的改进。1.x 中建立多个连接的消耗以及效率都存在问题,2.0 版本的多路复用多个请求共用一个连接,多个请求可以同时在一个 TCP 连接上并发。主要借助于二进制帧中的标识进行区分实现链路的复用;
  • 头部压缩 :2.0 版本使用使用 HPACK 算法对头部 Header 数据进行压缩,从而减少请求的大小提高效率。这个非常好理解,之前每次发送都要带相同的 Header,显得很冗余,2.0 版本对头部信息进行增量更新有效减少了头部数据的传输;
  • 服务端推送 :这个功能有点意思。之前 1.x 版本服务端都是收到请求后被动执行,在 2.0 版本允许服务器主动向客户端发送资源,这样在客户端可以起到加速的作用。

  • 2 HTTP/2.0 详解


    前面对比了几个版本的演进和优化过程,接下来深入研究下 2.0 版本的一些特性及其基本实现原理。


    从对比来看,2.0 版本并不是在 1.1 版本上的一些优化而是革新,因为 2.0 背负了更多的性能目标任务。1.1 虽然增加了长连接和管道化,但是从根本上并没有实现真正的高性能。


    2.0 的设计目标是在兼容 1.x 语义和操作的基础上,给用户带来更快捷、更简单、更安全的体验高效地利用当前的网络带宽。为此 2.0 做了很多调整,主要包括二进制化分帧、多路复用、头部压缩等。


    Akamai 做了 HTTP 2.0 和 HTTP 1.1 在加载过程中的对比效果(实验中加载 379 个小片段 在笔者的电脑上的加载时间是 0.99 秒 vs 5.80 秒)。


    https://http2.akamai.com/demo

    2.1 SPDY 协议


    要说 2.0 版本标准和新特性就必须提谷歌的 SPDY 协议,看一下百度百科:

    SPDY 是 Google 开发的基于 TCP 的会话层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY 并不是一种用于替代 HTTP 的协议,而是对 HTTP 协议的增强。


    新协议的功能包括数据流的多路复用、请求优先级以及 HTTP 报头压缩。谷歌表示引入 SPDY 协议后,在实验室测试中页面加载速度比原先快 64%。


    随后 SPDY 协议得到 Chrome、Firefox 等大型浏览器的支持,在一些大型网站和小型网站种部署。这个高效的协议引起了 HTTP 工作组的注意,在此基础上制定了官方 HTTP 2.0 标准。


    之后几年,SPDY 和 HTTP 2.0 继续演进相互促进。HTTP 2.0 让服务器、浏览器和网站开发者在新协议中获得更好的体验,很快被大众所认可。


    2.2 二进制分帧层


    二进制分帧层 binary framing layer 在不修改请求方法和语义的基础上,重新设计了编码机制,如图为 HTTP/2.0 分层结构。



    二进制编码机制使得通信可以在单个 TCP 连接上进行,该连接在整个对话期间一直处于活跃状态。


    二进制协议将通信数据分解为更小的帧,数据帧充斥在 C/S 之间的双向数据流中。就像双向多车道的高速路,来往如织川流不息:



    要理解二进制分帧层需要知道四个概念:


  • 链接 Link :就是指一条 C/S 之间的 TCP 链接,这是个基础的链路数据的高速公路;
  • 数据流 Stream :已建立的 TCP 连接内的双向字节流,TCP 链接中可以承载一条或多条消息;
  • 消息 Message :消息属于一个数据流,消息就是逻辑请求或响应消息对应的完整的一系列帧,也就是帧组成了消息;
  • 帧 Frame :帧是通信的最小单位,每个帧都包含帧头和消息体,标识出当前帧所属的数据流。

  • 四者是一对多的包含关系,笔者画了一张图方便理解。



    再来看一下 Headers Frame 头部帧的结构:



    再来看一下 Headers Frame 头部帧的结构:从各个域可以看到长度、类型、标志位、流标识符、数据净荷等,感兴趣可以阅读 RFC7540 相关文档。


    https://httpwg.org/specs/rfc7540.html


    总之,2.0 版本将通信数据分解为二进制编码帧进行交换,每个帧对应着特定数据流中的特定消息,所有帧和流都在一个 TCP 连接内复用。二进制分帧协议是 2.0 其他功能和性能优化的重要基础。


    2.3 多路复用


    1.1 版本中存在队首阻塞问题。因此如果客户端要发起多个并行请求来提升性能,必须使用多个 TCP 连接,这样就要承受更大延时和建链拆链成本,不能有效利用 TCP 链接。


    由于 2.0 版本中使用新的二进制分帧协议突破了 1.0 的诸多限制,从根本上实现了真正的请求和响应多路复用。


    客户端和服务器将交互数据分解为相互独立的帧,互不影响地交错传输,最后再在对端根据帧头中的流标识符把它们重新组装起来,从而实现了 TCP 链接的多路复用。


    下图展示了 2.0 版本的基于帧的消息通信过程:



    2.4 首部压缩


    Header 冗余传输


    我们都知道 HTTP 请求都有 Header 部分,每个包都有 Header。并且相对于一条链接而言,大部分包的 Header 部分都是相同的,每次传输相同的部分确实非常浪费。


    现代网络中每个网页平均包含 100 多个 HTTP 请求,每个请求头平均有 300-500 字节,总数据量达到几十 KB 以上,这样可能造成数据延时,尤其复杂的 WiFi 环境或者蜂窝网络,这样只能看到手机在转圈,但是这些请求头之间通常几乎没有变化,在本已经拥挤的链路中多次传输相同的数据部分确实不是高效做法。 基于 TCP 设计的拥塞控制具有线增积减 AIMD 特性,如果发生丢包那么传输速率将大幅度下降,这样在拥挤的网络环境中大的包头意味着只能加剧拥塞控制造成的低速率传输。


    HTTP 压缩和犯罪攻击


    在 2.0 版本的 HPACK 算法之前,HTTP 压缩使用 gzip 去压缩。后来提出的 SPDY 算法对 Headers 进行特殊设计,但是它依旧使用的是 DEFLATE 算法。


    在后面的一些实际应用中发现 DEFLATE 和 SPDY 都有被攻击的危险,因为 DEFLATE 算法使用后向字符串匹配和动态 Huffman 编码。攻击者可以控制部分请求头部,通过修改请求部分然后看压缩之后大小改变多少。如果变小了,攻击者就知道注入的文本和请求中的某些内容有重复。


    这个过程有点像俄罗斯方块的消除过程。这样经过一段时间的尝试,数据内容就可能被全部搞清楚。由于这种风险的存在才研发出更安全的压缩算法。


    HPACK 算法


    2.0 版本中 HPACK 算法在 C/S 中使用首部表来存储之前发送的键值对,对于相同的数据通信期间几乎不会改变的通用键值对只需发送一次即可。


    极端情况如果请求头每次没有变化。那么传输中则不包含首部,也就是首部开销就是零字节。如果首部键值对发生变化了,也只需要发送变化的数据,并且将新增或修改的首部帧会被追加到首部表,首部表在链接存活期始终存在, 并且由客户端和服务器共同更新和维护。


    简单说就是客户端和服务端共同维护了一个 key-value 的结构。发生变化时则更新传输,否则就不传输。这样相当于首次全量传输之后增量更新传输即可。这个思想在日常开发中也非常普遍,不用想得太复杂。


    下图展示了首部表的更新过程:



    HPACK 算法的相关文档:https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12


    2.5 服务端推送


    服务端推送是 2.0 版本新增的一个强大功能。与通常一问一答的 C/S 交互不同,推送式交互中服务器可以对客户端的一个请求发送多个响应。除了对最初请求的响应外还向客户端推送额外资源,无需客户端明确地请求也可以推送。


    想象一下你去餐厅吃饭。服务好的快餐厅在你点好一份牛肉面之后,还会给你送上餐巾纸、筷子、勺子甚至调料等。这样主动式的服务,节约了客人的时间并且提高了用餐体验。


    在实际的 C/S 交互中这种主动推送额外资源的方法很有效。因为几乎每个网络应用都会包含多种资源,客户端需要全部逐个获取它们,此时如果让服务器提前推送这些资源,从而可以有效减少额外的延迟时间,因为服务器可以知道客户端下一步要请求什么资源。


    下图为服务端推送的简单过程:



    3 HTTP/2.0 和 HTTP/3.0


    科技永不止步。


    我们都知道互联网中业务是不断迭代前进的,像 HTTP 这种重要的网络协议也是如此,新版本是对旧版本的扬弃。


    3.1 HTTP/2.0 和 TCP 的爱恨纠葛


    HTTP/2.0 是 2015 年推出的,还是比较年轻的。其中重要的是二进制分帧协议、多路复用、头部压缩、服务端推送等重要优化使 HTTP 协议真正上了一个新台阶。



    像谷歌这种重要的公司并没有满足于此,而且想继续提升 HTTP 的性能,花最少的时间和资源获取极致体验。


    那么肯定要问 HTTP/2.0 虽然性能已经不错了,还有什么不足吗?


  • 建立连接时间长(本质上是 TCP 的问题);
  • 队头阻塞问题;
  • 移动互联网领域表现不佳(弱网环境);
  • ......

  • 熟悉 HTTP/2.0 协议的同学应该知道,这些缺点基本都是由于 TCP 协议引起的。水能载舟亦能覆舟,其实 TCP 也很无辜呀。


    在我们眼里,TCP 是面向连接、可靠的传输层协议,当前几乎所有重要的协议和应用都是基于 TCP 来实现的。


    网络环境的改变速度很快,但是 TCP 协议相对缓慢。正是这种矛盾促使谷歌做出了一个看似出乎意料的决定——基于 UDP 来开发新一代 HTTP 协议。


    3.2 谷歌为什么选择 UDP


    上文提到,谷歌选择 UDP 是看似出乎意料的,仔细想一想其实很有道理。


    我们单纯地看看 TCP 协议的不足和 UDP 的一些优点:


  • 基于 TCP 开发的设备和协议非常多,兼容困难;
  • TCP 协议栈是 Linux 内部的重要部分,修改和升级成本很大;
  • UDP 本身是无连接的、没有建链和拆链成本;
  • UDP 的数据包无队头阻塞问题;
  • UDP 改造成本小。

  • 从上面的对比可以知道,谷歌要想从 TCP 上进行改造升级绝非易事,但是 UDP 虽然没有 TCP 为了保证可靠连接而引发的问题,但是 UDP 本身不可靠,又不能直接用。



    综合而知,谷歌决定在 UDP 基础上改造一个具备 TCP 协议优点的新协议也就顺理成章了。这个新协议就是 QUIC 协议。


    3.3 QUIC 协议和 HTTP/3.0


    QUIC 其实是 Quick UDP Internet Connections 的缩写,直译为快速 UDP 互联网连接。



    我们来看看维基百科对于 QUIC 协议的一些介绍:


    QUIC 协议最初由 Google 的 Jim Roskind 设计,实施并于 2012 年部署,在 2013 年随着实验的扩大而公开宣布,并向 IETF 进行了描述。


    QUIC 提高了当前正在使用 TCP 的面向连接的 Web 应用程序的性能。它在两个端点之间使用用户数据报协议(UDP)建立多个复用连接来实现此目的。


    QUIC 的次要目标包括减少连接和传输延迟,在每个方向进行带宽估计以避免拥塞。它还将拥塞控制算法移动到用户空间,而不是内核空间,此外使用前向纠错(FEC)进行扩展,以在出现错误时进一步提高性能。


    HTTP/3.0 又称为 HTTP Over QUIC,它弃用 TCP 协议,改为使用基于 UDP 协议的 QUIC 协议来实现。

    4 QUIC 协议


    择其善者而从之,其不善者而改之。


    HTTP/3.0 既然选择了 QUIC 协议,也就意味着 HTTP/3.0 基本继承了 HTTP/2.0 的强大功能,并且进一步解决了 HTTP/2.0 存在的一些问题,同时必然引入了新的问题。



    QUIC 协议必须要实现 HTTP/2.0 在 TCP 协议上的重要功能,同时解决遗留问题。


    我们来看看 QUIC 是如何实现的。


    4.1 队头阻塞问题


    队头阻塞 Head-of-line blocking(缩写为 HOL blocking)是计算机网络中是一种性能受限的现象,通俗来说就是:一个数据包影响了一堆数据包,它不来大家都走不了。


    队头阻塞问题可能存在于 HTTP 层和 TCP 层,在 HTTP/1.x 时两个层次都存在该问题。



    HTTP/2.0 协议的多路复用机制解决了 HTTP 层的队头阻塞问题,但是在 TCP 层仍然存在队头阻塞问题。


    TCP 协议在收到数据包之后,这部分数据可能是乱序到达的。但是 TCP 必须将所有数据收集排序整合后给上层使用,如果其中某个包丢失了,就必须等待重传。从而导致某个丢包数据阻塞整个连接的数据使用。


    QUIC 协议是基于 UDP 协议实现的,在一条链接上可以有多个流,流与流之间是互不影响的,当一个流出现丢包影响范围非常小,从而解决队头阻塞问题。


    4.2 0-RTT 建链


    衡量网络建链的常用指标是 RTT Round-Trip Time,也就是数据包一来一回的时间消耗。


    RTT 包括三部分:往返传播时延、网络设备内排队时延、应用程序数据处理时延。



    一般来说 HTTPS 协议要建立完整链接包括 TCP 握手和 TLS 握手。总计需要至少 2-3 个 RTT,普通的 HTTP 协议也需要至少 1 个 RTT 才可以完成握手。


    然而,QUIC 协议可以实现在第一个包就可以包含有效的应用数据,从而实现 0-RTT,但这也是有条件的。



    简单来说,基于 TCP 协议和 TLS 协议的 HTTP/2.0 在真正发送数据包之前需要花费一些时间来完成握手和加密协商,完成之后才可以真正传输业务数据。


    但是 QUIC 则第一个数据包就可以发业务数据,从而在连接延时有很大优势,可以节约数百毫秒的时间。


    QUIC 的 0-RTT 也是需要条件的,对于第一次交互的客户端和服务端 0-RTT 也是做不到的,毕竟双方完全陌生。


    因此,QUIC 协议可以分为首次连接和非首次连接,两种情况进行讨论。


    4.3 首次连接和非首次连接


    使用 QUIC 协议的客户端和服务端要使用 1RTT 进行密钥交换,使用的交换算法是 DH(Diffie-Hellman)迪菲-赫尔曼算法。


    DH 算法开辟了密钥交换的新思路,在之前的文章中提到的 RSA 算法也是基于这种思想实现的,但是 DH 算法和 RSA 的密钥交换不完全一样,感兴趣的读者可以看看 DH 算法的数学原理。


    DH 算法开辟了密钥交换的新思路,在之前的文章中提到的 RSA 算法也是基于这种思想实现的,但是 DH 算法和 RSA 的密钥交换不完全一样,感兴趣的读者可以看看 DH 算法的数学原理。


    4.3.1 首次连接


    简单来说一下,首次连接时客户端和服务端的密钥协商和数据传输过程,其中涉及了 DH 算法的基本过程:


  • 客户端对于首次连接的服务端先发送 client hello 请求;

  • 服务端生成一个素数 p 和一个整数 g,同时生成一个随机数   (笔误,此处应该是 Ks_pri)为私钥,然后计算出公钥   =   mod p,服务端将 、p、g 三个元素打包称为 config,后续发送给客户端;

  • 客户端随机生成一个自己的私钥  ,再从 config 中读取 g 和 p,计算客户端公钥   =   mod p;

  • 客户端使用自己的私钥   和 服务端发来的 config 中读取的服务端公钥 ,生成后续数据加密用的密钥 K =   mod p;

  • 客户端使用密钥 K 加密业务数据,并追加自己的公钥  ,都传递给服务端;

  • 服务端根据自己的私钥  和 客户端公钥  生成客户端加密用的密钥 K =   mod p;

  • 为了保证数据安全,上述生成的密钥 K 只会生成使用 1 次,后续服务端会按照相同的规则生成一套全新的公钥和私钥,并使用这组公私钥生成新的密钥 M;

  • 服务端将新公钥和新密钥 M 加密的数据发给客户端,客户端根据新的服务端公钥和自己原来的私钥计算出本次的密钥 M,进行解密;

  • 之后的客户端和服务端数据交互都使用密钥 M 来完成,密钥 K 只使用 1 次。




  • 4.3.2 非首次连接


    前面提到客户端和服务端首次连接时服务端传递了 config 包,里面包含了服务端公钥和两个随机数,客户端会将 config 存储下来,后续再连接时可以直接使用,从而跳过这个 1RTT,实现 0-RTT 的业务数据交互。


    客户端保存 config 是有时间期限的,在 config 失效之后仍然需要进行首次连接时的密钥交换。


    4.4 前向安全问题


    前向安全是密码学领域的专业术语,看下百度上的解释:


    前向安全或前向保密 Forward Secrecy 是密码学中通讯协议的安全属性,指的是长期使用的主密钥泄漏不会导致过去的会话密钥泄漏。


    前向安全能够保护过去进行的通讯不受密码或密钥在未来暴露的威胁,如果系统具有前向安全性,就可以保证在主密钥泄露时历史通讯的安全,即使系统遭到主动攻击也是如此。


    通俗来说,前向安全指的是密钥泄漏也不会让之前加密的数据被泄漏,影响的只有当前,对之前的数据无影响。


    前面提到 QUIC 协议首次连接时先后生成了两个加密密钥,由于 config 被客户端存储了,如果期间服务端私钥  泄漏,那么可以根据 K =   mod p 计算出密钥 K。


    如果一直使用这个密钥进行加解密,那么就可以用 K 解密所有历史消息。因此后续又生成了新密钥,使用其进行加解密。当完成交互时则销毁,从而实现了前向安全。



    4.5 前向纠错


    前向纠错是通信领域的术语,看下百科的解释:


    前向纠错也叫前向纠错码 Forward Error Correction 简称 FEC 是增加数据通讯可信度的方法,在单向通讯信道中,一旦错误被发现,其接收器将无权再请求传输。


    FEC 是利用数据进行传输冗余信息的方法,当传输中出现错误,将允许接收器再建数据。


    听这段描述就是做校验的,看看 QUIC 协议是如何实现的:


    QUIC 每发送一组数据就对这组数据进行异或运算,并将结果作为一个 FEC 包发送出去,接收方收到这一组数据后根据数据包和 FEC 包即可进行校验和纠错。


    4.6 连接迁移


    网络切换几乎无时无刻不在发生。


    TCP 协议使用五元组来表示一条唯一的连接,当我们从 4G 环境切换到 WiFi 环境时,手机的IP地址就会发生变化,这时必须创建新的 TCP 连接才能继续传输数据。


    QUIC 协议基于 UDP 实现摒弃了五元组的概念,使用 64 位的随机数作为连接的 ID,并使用该 ID 表示连接。


    基于 QUIC 协议之下,我们在日常 WiFi 和 4G 切换时,或者不同基站之间切换都不会重连,从而提高业务层的体验。



    通过前面的一些介绍我们可以看出 QUIC 协议虽然是基于 UDP 来实现的,但是它将 TCP 的重要功能都进行了实现和优化,否则使用者是不会买账的。


    QUIC 协议的核心思想是,将 TCP 协议在内核实现的诸如可靠传输、流量控制、拥塞控制等功能转移到用户态来实现,同时在加密传输方向的尝试也推动了 TLS 1.3 的发展。


    但是 TCP 协议的势力过于强大,很多网络设备甚至对于 UDP 数据包做了很多不友好的策略,进行拦截从而导致成功连接率下降。


    主导者谷歌在自家产品做了很多尝试,国内腾讯公司也做了很多关于 QUIC 协议的尝试。其中,腾讯云对 QUIC 协议表现了很大的兴趣,并做了一些优化然后在一些重点产品中对连接迁移、QUIC 成功率、弱网环境耗时等进行了实验,给出了来自生产环境的诸多宝贵数据。


    简单看一组腾讯云在移动互联网场景下的不同丢包率下的请求耗时分布:



    任何新生事物的推动都是需要时间的,出现多年的 HTTP/2.0 和 HTTPS 协议的普及度都没有预想高,IPv6 也是如此。不过 QUIC 已经展现了强大的生命力,让我们拭目以待吧!


    总结


    本文通过介绍 HTTP 协议的历史演进、各个版本的主要特征和优缺点、重点介绍了HTTP/2.0 协议的一些特性,包括 SPDY 协议、二进制分帧协议、多路复用、首部压缩、服务端推送等重要功能,篇幅有限不能展开太多。


    虽然 HTTP/2.0 版本协议有很多非常优秀的功能,并且在 2015 年正式发布。现在国内外一些大厂基本都有使用 HTTP/2.0 承担部分请求,但是目前仍然未广泛普及。


    目前 HTTP/3.0 版本在 2018 年也推出来了,至于 HTTP/2.0 和 HTTP/3.0 的推广和普及是需要时间的,但是坚信我们的网络可以更安全、更快捷、更节约。


    不过现在看看 QUIC 协议基于 UDP 主体将 TCP 的重要功能转移到用户空间来实现,从而绕开内核实现用户态的 TCP 协议,但是真正实现起来还是非常复杂的。


    网络协议本身就很复杂,本文只能从整体出发对重要的部分做粗浅的阐述,如果对某个点很感兴趣,可以查阅相关代码和 RFC 文档。


    技术进步也非朝夕之功,需要在实践中反复锤炼。


    - EOF -

    推荐阅读   点击标题可跳转

    1、10 分钟讲完 QUIC 协议

    2、关于 HTTP 后端人员需要了解的 20+ 图片!

    3、面试 HTTP ,99% 的面试官都爱问这些问题


    看完本文有收获?请转发分享给更多人

    关注「ImportNew」,提升Java技能

    点赞和在看就是最大的支持❤️