http1.x与http2

http1.x

Http: 文本传输协议(HyperText Transfer Protocol), 位于计算机网络五层中的应用层,基于tcp之上.

http 瓶颈与优化

长连接

在http/1.1中引入keepalive后,不需要在每个request都要进行tcp握手了,请求状况从图1演变成了图2
"图1"
"图2"

http pipeline

持久http允许重用现有的连接,但意味着要遵从FIFO排队顺序:请求调度->等待完整响应->发送下一个请求,http pipeline是把多个HTTP请求放到一个TCP连接中一一发送,而在发送过程中不需要等待服务器对前一个请求的响应。 如图3:
"图3"
但是由于http/1.x协议的限制:不会严格序列化返回的响应,http/1.x不允许来自多个响应的数据在相同的连接上交错(多路复用),从而使每个响应的字节在下一个响应之前被完全返回。如图4:
"图4"

  • html与css请求并发,html先于css
  • 服务器开始处理。html: 40ms, css: 20ms。
  • css请求先完成,但必须等待,知道html响应完成
  • html响应完毕,发送css
    即使客户端发出了两个请求,并且可以首先使用css资源,但服务器必须等待htm响应完成后才能发送css,这被称为线头阻塞(Head of line blocking),如果第一个请求无限挂起,背后的请求都必须等待。
    在工程中,由于缺乏多路复用,http pipeline有很多影响,所以大部分浏览器都是禁用的。

    多个TCP连接

    由于在http/1.x中没有多路复用,所以浏览器使用多个TCP连接(每个主机一般为6个),但是连接的管理带来了额外的内存和CPU开销。

    域分片(Sharding)

    由于http/1.x对客户端tcp连接数目有限制,对于一些大型网站,这是不够用的,所以可以把资源放在多个子域上,由于主机名不同,这样做等于隐式地增加了浏览器的连接限制。但是这样做会带来额外的DNS查找,为每个额外的套接字消耗资源,而且要手动管理资源分配的地点和方式

    减少请求数目

    spriting

    Spriting是一种将很多较小的图片合并成一张大图,再用JavaScript或者CSS将小图重新“切割”出来的技术。网站可以利用这一技巧来达到提速的目的——在HTTP 1.1里,下载一张大图比下载100张小图快得多。

    内联(lnlining)

    Inlining是另外一种防止发送很多小图请求的技巧,它将图片的原始数据嵌入在CSS文件里面的URL里。

    .icon1 {
        background:url(data:image/png;base64,<data>) no-repeat;
    }
    .icon2 {
        background: url(data:image/png;base64,<data>) no-repeat;
    }
    

    拼接(Concatenation)

    大型网站往往会包含大量的JavaScript文件。一些前端工具可以帮助开发人员将这些文件合并为一个大的文件,从而让浏览器能只花费一个请求就将其下载完,而不是发无数请求去分别下载那些琐碎的JavaScript文件。
    这三个技术的缺陷:

  • 需要额外的预处理,部署注意事项和代码
  • 任何一个单独的文件单一更新都会重新下载整个文件,导致高字节开销
  • 只有当传输完成后,javascript和css才被解析和执行,会延迟应用程序的执行速度
  • 对于spriting,由于浏览器必须解码整个图像将其存在内存中,图像会占用大量的内存

    头部开销

    现在,每个http request的header中都一般会占据大量的字节,尤其是cookie,http协议是无状态的,所以一般request里面都会带有cookie,这造成了巨大的开销。

    HTTPS

    HTTPS = HTTP + TLS,HTTPS多了tls握手的消耗。

HTTP2

SPDY

Google开发的一个协议,http2基于基于SPDY/3草案进行一些修改之后发布了http2的draft-00。

二进制分帧层

HTTP2 是一个二进制协议, 所有性能增强的核心在于新的二进制分帧层。HTTP/1.x协议以换行符作为纯文本的分隔符,而HTTP/2将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码。
"图5"

  • 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息。
  • 消息:与逻辑请求或响应消息对应的完整的一系列帧。
  • 帧:HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流。
  • 所有通信都在一个 TCP 连接上完成,此连接可以承载任意数量的双向数据流。
  • 每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。
  • 每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。
  • 帧是最小的通信单位,承载着特定类型的数据,例如HTTP标头、消息负载,等等。来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

    HTTP2特性

    多路复用

    每个单独的http2连接都可以包含多个并发的流,这些流中交错的包含着来自两端的帧。流既可以被客户端/服务器端单方面的建立和使用,也可以被双方共享,或者被任意一边关闭。在流里面,每一帧发送的顺序非常关键。接收方会按照收到帧的顺序来进行处理。流的多路复用意味着在同一连接中来自各个流的数据包会被混合在一起。所以级联文件、image sprites 和域名分片都不必要使用了。

    数据流优先级和依赖性

    HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系,,我们可以根据用户互动和其他信号更改依赖关系和重新分配权重。这样当用户滚动一个全是图片的页面的时候,浏览器就能够指定哪个图片拥有更高的优先级。或者是在你切换标签页的时候,浏览器可以提升新切换到页面所包含流的优先级。

    流控制

    每个http2流都拥有自己的公示的流量窗口,它可以限制另一端发送数据。HTTP/2未指定任何特定算法来实现流控制。不过,它提供了简单的构建块并推迟了客户端和服务器实现,可以实现自定义策略来调节资源使用和分配。

    头压缩

    HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:
  • 这种格式支持通过静态 Huffman 代码对传输的标头字段进行编码,从而减小了各个传输的大小。
  • 这种格式要求客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表,此列表随后会用作参考,对之前传输的值进行有效编码。

    服务器推送

    HTTP/2 打破了严格的请求-响应语义,服务器可以对一个客户端请求发送多个响应,服务器可以向客户端推送额外资源,而无需客户端明确地请求。

参考资料: