Skip to main content

HTTP 版本

HTTP 1.0

请求方法

  • 只有 GETPOSTHEAD请求方法

无法复用连接

HTTP 1.0-无法复用连接

  • 每次请求或者响应都需要建立关闭一个独立的TCP链接。增加了网络延迟和开销。
  • 不支持长连接的机制,导致频繁的TCP链接建立和关闭,影响性能。
  • 不能充分利用宽带资源,造成带宽资源的浪费
info

因为TCP 协议 慢启动的特点,即一开始传输的时候数据量少,一段时间之后达到传输的峰值。 所以按照 HTTP1.0 这种传输方式,会导致大量的请求在 TCP 达到传输峰值就已经结束了。

队头堵塞

HTTP 1.0-队头堵塞

  • 一个 TCP 链接 不能同时处理多个请求,造成请求处理的顺序依赖于响应的完成。也就是队头堵塞的原因

缓存机制

  • HTTP1.0缓存机制相对简单,主要通过 Expires实现。 缺少完善的缓存机制缓存策略

HTTP 1.1

长连接

HTTP 1.1-长连接

  • HTTP 1.1 默认开启长连接,
  • 支持长连接,可以在一个TCP 链接上处理多个请求/响应
  • 减少 TCP 链接 频繁的创建关闭。同时减少了TCP三次握手四次挥手的时间
  • 因为TCP 协议 慢启动的特点, 长连接可以充分有效的利用带宽。
info

Connection:keep-alive 是为了解决HTTP 1.0不支持长连接使用的请求头。

缓存机制

请求方法

  • 新增了OPTIONS,PUT,DELETE,TRACE,CONNECT,PATCH等方法。

管道化

HTTP 1.1-长连接

HTTP 1.1允许在响应到达之前发送下一个请求,这样可以大幅度缩减带宽限制时间。

  • 多个 HTTP 请求不用依赖上一个响应的完成,可以批量发送,这就解决了 HTTP 队头阻塞问题
  • 但是批量发送的请求,服务器必须要按照请求到达的顺序返回。仍然没有彻底解决队头堵塞的问题
info

由于多个请求使用的是同一个TCP 链接,服务器必须要按照请求到达的顺序返回。

因为 HTTP 是一个无状态协议, 每个请求和响应并没有序号标识,无法将乱序的响应与请求关联起来。

除了这些管道化可能会带来一些意料之外的结果,所以现代浏览器基本都没有支持这个特性。

因为HTTP1.1还是存在队头堵塞的问题,我们需要对一些大量HTTP 请求的网站使用网络性能优化

HTTP 2

HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法 / 状态码 / 语义都与 HTTP/1.1 一样。

从目前的情况来看,国内外一些排名靠前的站点基本都实现了 HTTP 2.0 的部署,使用 HTTP 2.0能带来 20%~60% 的效率提升。

可以通过这个图片直观感受下 HTTP/2HTTP/1.1 到底快了多少

HTTP/2和HTTP/1.x性能比较

基本概念

  • 帧(Frame):通信的基本单位。一个 TCP 连接上可以有任意数量的流。
  • 流(Stream): 已建立的 TCP 连接上的双向字节流,可以承载一个或多个消息。
  • 消息(Message): 一个完整的 HTTP 请求响应,由一个或多个帧(Frame)组成。特定消息的帧(Frame)在同一个上发送,这意味着一个 HTTP 请求或响应只能在一个**流(Stream)**上发送。

二进制帧

HTTP/2 是如何做到「突破 HTTP/1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量」的 ?

关键之一就是在 应用层(HTTP/2)传输层(TCP or UDP) 之间增加一个二进制分帧层

HTTP/2-二进制帧-1

  • HTTP/2 会将所有的传输信息分割为更小的消息和帧(frame),并对他们采用二进制格式的编码。
  • HTTP/1.x的头部信息会被封装到HEADERS 帧,对应的Request Body则封装到 DATA 帧里面。
  • HTTP/2 数据分帧后,“Header+Body"的报文结构就完全消失了,协议看到的只是一个个"碎片”。

HTTP/2-二进制帧-2

  • 每个数据流都以消息(Message) 的形式发送,而消息(Message) 又由一个或多个 帧(Frame) 组成。
  • 多个帧(Frame) 之间可以乱序发送,根据帧(Frame) 首部的流(Stream) 标识符可以重新组装完整的消息(Message)

多路复用

HTTP/2中,同域名下所有通信都在单个 TCP 连接 上完成, 解决了浏览器限制同一个域名下请求数量的问题。

规避了TCP 连接慢启动的特点,也更容易充分利用带宽资源,实现全速传输。这一特性使得 HTTP 传输性能得到极大提升。

多工

HTTP/2中 复用 TCP 连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了队头堵塞的问题。

多工

优先级

HTTP/2 中,每个请求都可以带一个 31bit 的优先值,0表示最高优先级,数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流(Stream)消息(Message)帧(Frame)

Header 压缩(HPACK)

HTTP/2之前,所有的消息头都是以字符串的形式完整传递的。实际上大部分的请求头字段有很多都是重复的,比如 CookieUser Agent

  • HTTP/2为此采用 HPACK 压缩头部,来减少消息头的体积。
  • 客户端服务器共同维护一个消息头的静态表,包含常见的头部名称,以及常见的头部名称和值的组合。
  • 客户端服务器维护一份相同的动态字典,可以动态的添加内容。

所以我们在传输消息头的时候,先尝试从静态表或者动态表进行查询匹配,对应的索引值。

如果静态表或者动态表 都没有匹配到,通过 Huffman 压缩后进行传输,同时浏览器或者服务端会把它添加到自己的动态表中。

HTTP/2 的静态字典(只截取了部分,完整表格在这里): HTTP/2-静态表

服务器推送

HTTP/2允许在客户端没有主动请求的情况下,向客户端发送资源,服务端预先会把资源推送给服务端。

当客户端后续需要请求资源的时候,自动从之前推送的资源中去寻找。

这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下也可以使用 prefetch

warning

服务端可以主动推送,客户端也可以主动选择是否接收。

如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收,另外,主动推送也遵守同源策略