HTTP2.0

最初的 HTTP

HTTP 刚刚诞生之初只用于 web 端的内容获取,一般就是用于页面访问,那个时候的页面内容还不如现在这样丰富,交互场景也不是很多,也没有庞大繁杂的 CSS、JS ,页面加载速度非常快。但是随着 web 2.0 的出现以及更多的内容被展示、更精美的排版、更多的用户交互场景一起出现,导致页面的内容越来越大,使得页面加载速度越来越慢。

HTTP的基本优化

影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。

带宽

如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。

延迟

浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。

HTTP1.0和HTTP1.1的一些区别

HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使错误通知的管理,在HTTP1.1中新增了2用最为广泛的HTTP协议。 主要区别主要体现在:

  1. 缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  2. 带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。4个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  3. Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
  4. 长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。

SPDY

虽然 HTTP1.0 和 HTTP 1.1 存在这么多问题,业界也是想出了各种优化手段,但是这些手段怎么说呢,都是治标不治本,直到 2020 年 Google 提出了 SPDY 的方案,大家才开始从正面看待和解决老版本 HTTP 协议本身的问题,这也直接加速了 HTTP 2.0 的诞生。
我们先来聊一下 SPDY 是什么,它都有哪些特点?

认识 SPDY

SPDY 的目标在于解决 HTTP 的缺陷,即延迟和安全性。我们上面一直在讨论延迟,至于安全性,虽然我们上面没有具体聊,不过 HTTP 的明文传输确是个问题。如果以降低延迟为目标,应用层的 HTTP 和传输层的 TCP 都是都有调整的空间,不过 TCP 作为更底层协议存在已达数十年之久,其实现已深植全球的网络基础设施当中,如果要动必然伤经动骨,业界响应度必然不高,所以 SPDY 的手术刀对准的是 HTTP 。

  • 降低延迟,客户端的单连接单请求,服务端的 FIFO 响应队列都是延迟的大头。
  • HTTP 最初设计都是客户端发起请求,然后服务端进行响应,服务端无法主动发送内容到客户端。
  • 压缩 HTTP header,HTTP 1.x 的 header 越来越膨胀,cookie 和 user agent 很容易让 header 的 size 增至1kb 大小甚至更多。而且由于 HTTP 的无状态特性,header 必须每次请求都重复携带,很浪费流量。
    为了增加解决这些问题的可行性,聪明的 Google 一开始就避开了从传输层动手,而且打算利用开源社区的力量以提高扩散的力度,对于协议使用者来说,也只需要在请求的 header 里设置 user agent,然后在服务端做好支持即可,极大的降低了部署的难度。SPDY 的设计如下

可以看到,SPDY 位于 HTTP 之下,SSL 之上,这样可以轻松的兼容老版本的 HTTP 协议,SPDY 的功能分为基础功能和高级功能两部分,基础功能是默认启用的,高级功能需要手动启用。

SPDY 基础功能

  • 多路复用(multiplexing),多路复用通过多个请求共用一个连接的方式,降低了 TCP 连接建立和释放的开销,同时提高了带宽的利用率。
  • 请求优先级(request prioritization),多路复用带来的一个问题是,在共享连接的基础上会存在一些关键请求被阻塞,SPDY 允许给每个请求设置优先级,这样重要的请求就会优先得到响应。
  • header 压缩,前面提到的 HTTP 1.x 的 header 很多时候都是重复而且多余的。选择合适的压缩算法可以减小包的大小和数量。SPDY 对 header 的压缩素可以达到 80% 以上。

SPDY 高级功能

  • 服务端推送,HTTP 只能由客户端发送,服务器只能被动发送响应。不过在开启服务端推送后,服务端通过 X-Associated-Content header 会告知服务器会有新的内容被推送过来,
  • 服务端暗示,和服务端推送所不同的是,服务端暗示不会推送内容,只是告诉客户端有新的内容产生,,内容的下载还是需要客户端主动发起请求。服务端暗示通过 X-Subresources header 来通知,一般应用场景是客户端需要先查询服务端状态,然后再下载资源,可以节约一次查询请求。

自动 SPDY 出现后,页面加载时间相比于 HTTP 减少了 64%,而且各大浏览器厂商在 SPDY 诞生之后的 1 年多时间里也都陆续支持了 SPDY。但是,SPDY 的生存时间却没有人们想象中的那么长,SPDY 从 2012 年诞生到 2016 年停止维护,如果 HTTP 2.0 没有诞生,我相信 Google 可能会收到更多的真实反馈和数据,但是 SPDY 在这段时间里也完成了自己的使命。

初探 HTTP 2.0

HTTP 2.0 也被写作 HTTP/2 ,它是超文本传输协议的 2.0 版本,因为 SPDY 的流行让 IETF 看到了优化后的效果,以及可以通过修改协议层来优化 HTTP,所以 IETF 开始决定正式考虑制定 HTTP 2.0 的计划,而且,SPDY的部分设计人员也被邀请参与了 HTTP 2.0 的设计。
HTTP2.0 在设计之初就与 SPDY 的设计目的和出发点不同,SPDY 更像是 Google 自家的一个产品,相当于自家的一个玩具,你怎么玩儿都行,而 HTTP 2.0 在设计之初就是为了普适性的这个目的,所以,一开始任何的设计都会关系到以后的维护问题,如果有什么瑕疵或者不足的地方可能会影响巨大,所以考虑的问题角度要非常严谨和慎重。

HTTP 2.0 在设计之初就有一些重要的前提:

  • 客户端向服务器发送请求的这种基本模型不会改变。
  • 原有的协议头不会改变,使用 http:// 和 https:// 的服务和应用不会做任何修改,不会有 http2://。
  • 使用 HTTP 1.x 的客户端和服务器可以平滑升级到 HTTP 2.0 上。
  • 不识别 HTTP 2.0 的代理服务器可以将请求降级到 HTTP 1.x。

客户端在和服务器确定是使用 HTTP1.x 还是 HTTP 2.0 之前,需要先确定对方是否支持 HTTP 2.0,所以这里必须要先进行协商,也就是客户端询问服务器,这样一来一回就多了一个 RTT 的延迟。我们对 HTTP 1.x 的修改就是为了降低延迟,现在又多了一个 RTT,这样显然是无法接受的。Google 制定 SPDY 协议的时候也遇到了这个问题,他们采取的做法是强制协商在 SSL 层完成,还因此制定了一个 TLS 的拓展,叫做 NPN(Next Protocol Negotiation)。虽然 HTTP 2.0 也采用了相同的方式,不过经过讨论后,最终 HTTP 2.0 没有强制要走 SSL 层,HTTP 2.0 没有使用 NPN,却制定了一个 TLS 的拓展叫做 ALPN(Application Layer Protocol Negotiation),现在,SPDY 也打算迁移到 ALPN 了。

二进制分层

二进制分帧层,是HTTP 2.0性能增强的核心。 HTTP 1.x在应用层以纯文本的形式进行通信,而HTTP 2.0将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。这样,客户端和服务端都需要引入新的二进制编码和解码的机制。 如下图所示,HTTP 2.0并没有改变HTTP 1.x的语义,只是在应用层使用二进制分帧方式传输。

下面这幅图很好的诠释了 HTTP1.x 和 HTTP 2.0 使用的不同报文格式。

帧 (frame)

HTTP 2.0通信的最小单位,包括帧首部、流标识符、优先值和帧净荷等。

其中,帧类型又可以分为:
DATA:用于传输HTTP消息体;
HEADERS:用于传输首部字段;
SETTINGS:用于约定客户端和服务端的配置数据。比如设置初识的双向流量控制窗口大小;
WINDOW_UPDATE:用于调整个别流或个别连接的流量
PRIORITY: 用于指定或重新指定引用资源的优先级。
RST_STREAM: 用于通知流的非正常终止。
PUSH_PROMISE: 服务端推送许可。
PING: 用于计算往返时间,执行“ 活性” 检活。
GOAWAY: 用于通知对端停止在当前连接中创建流。

消息(message)

消息是指逻辑上的HTTP消息(请求/响应)。一系列数据帧组成了一个完整的消息。比如一系列DATA帧和一个HEADERS帧组成了请求消息。

流(stream)

流是连接中的一个虚拟信道,可以承载双向消息传输。每个流有唯一整数标识符。为了防止两端流ID冲突,客户端发起的流具有奇数ID,服务器端发起的流具有偶数ID。所有HTTP 2. 0 通信都在一个TCP连接上完成, 这个连接可以承载任意数量的双向数据流Stream。 相应地, 每个数据流以 消息的形式发送, 而消息由一 或多个帧组成, 这些帧可以乱序发送, 然后根据每个帧首部的流标识符重新组装。

多路复用共享连接

基于二进制分帧层,HTTP 2.0可以在共享TCP连接的基础上,同时发送请求和响应。HTTP消息被分解为独立的帧,而不破坏消息本身的语义,交错发送出去,最后在另一端根据流ID和首部将它们重新组合起来。 我们来对比下HTTP 1.x和HTTP 2.0,假设不考虑1.x的pipeline机制,双方四层都是一个TCP连接。客户端向服务发起三个图请求/image1.jpg,/image2.jpg,/image3.jpg。 HTTP 1.x发起请求是串行的,image1返回后才能再发起image2,image2返回后才能再发起image3。

HTTP 2.0建立一条TCP连接后,并行传输着3个数据流,客户端向服务端乱序发送stream1~3的一系列的DATA帧,与此同时,服务端已经在返回stream 1的DATA帧 。

性能对比,高下立见。HTTP 2.0成功解决了HTTP 1.x的队首阻塞问题(TCP层的阻塞仍无法解决),同时,也不需要通过pipeline机制多条TCP连接来实现并行请求与响应。减少了TCP连接数对服务器性能也有很大的提升。

头部压缩

上面还聊到了 HTTP1.x 中的 header 由于 cookie 和 user agent 不存在记忆性,这样导致每次都要带着这些头重新发送请求,HTTP 2.0 使用 encoder 来减少传输的 header 大小,通信双方会各自缓存一份 header 字段表,这样能够避免重复传输 header ,也能够减小传输的大小。HTTP 2.0 采用的是 HPACK 压缩算法。

请求优先级

流可以带有一个31bit的优先级:
0:表示最高优先级
231-1:表示最低优先级
客户端明确指定优先级,服务端可以根据这个优先级作为依据交互数据,比如客户端优先级设置为.css>.js>.jpg(具体可参见《高性能网站建设指南》), 服务端按优先级返回结果有利于高效利用底层连接,提高用户体验。 然而,也不能过分迷信请求优先级,仍然要注意以下问题:

  • 服务端是否支持请求优先级
  • 会否引起队首阻塞问题,比如高优先级的慢响应请求会阻塞其他资源的交互。

服务器推送

HTTP2.0新增的一个强大的新功能,就是服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确的请求。
服务端根据客户端的请求,提前返回多个响应,推送额外的资源给客户端。如下图,客户端请求stream 1(/page.html)。服务端在返回stream 1的消息的同时推送了stream 2(/script.js)和stream 4(/style.css)
服务端推送是一种在客户端请求之前发送数据的机制。在HTTP2.0中,服务器可以对一个客户端的请求发送多个响应。如果一个请求是由你的主页发送的,服务器可能会响应主页内容、logo以及样式表,因为他知道客户端会用到这些东西。这样不但减轻了数据传送冗余步骤,也加快了页面响应的速度,提高了用户体验。
推送的缺点:所有推送的资源都必须遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方的确认才行。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇