欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

前端与HTTP

程序员文章站 2022-07-02 17:06:01
http/1.0、http/1.1、http/2都有哪些不同的机制,经历了哪些变革,对前端优化有什么样的影响? ......

本文整理在,我的github 上。欢迎star。

各版本的http

发展

在http建立之初,主要是为了传输超文本标记语言(html)文档。随着时代的发展,也进行了若干次演进。下图是各个版本发布的时间轴。
前端与HTTP

目前为止,使用最为广泛的是http1.1http1.0应该比较少了,最新的是http2
这篇博文也主要,围绕着1.0、1.1、2.0三个版本进行介绍。

http/1.0

http1.0不会复用tcp链接,每次请求都会打开、断开一条链接。
如果您看过我前阵子整理的关于tcp的博文,您就会知道,tcp是有延迟响应机制的,每次请求并不会马上返回。这算是http1.0性能不好的一个原因吧。

前端与HTTP

http/1.1

http/1.1当前普及程度最高的http版本。
到了http/1.1版本,tcp链接可以持久保持了(也就说,一段时间内,一个tcp链接会等到同一个域名下的所有资源加载完后再断开。)

前端与HTTP

在保持tcp链接的基础上,引入了http管道的机制,差点实现了多路复用

http/1.1 without pipelining(不使用管道)

通过一条tcp链接请求资源,只有在上一个请求完成后,才能发出下一个请求。也就是上图描述的情形。

http/1.1 with pipelining(使用管道)

客户端不会等待响应,直接并发n个请求。但是,http/1.x有严格的串行返回响应机制。通俗的讲就是:请求时,不用等上一个完成;但响应时,必须严格按照顺序返回
通过开发者工具,你就可以观察到这一点。

前端与HTTP

基于以上描述,使用“ http 管道”技术时,万一第一个响应时间很长,那么后面的响应处理完了也无法发送,只能被缓存起来,占用服务器内存,这就是传说中的“队首阻塞(head of line blocking)”。
这也是http/1.x下,多数网络体验不好的原因。

http/2.0

在介绍http/2.0之前,我们来先看一份akamai公司提供的一个官方演示

这里用了361(19*19)张图片,分别使用http/1.1,http/2.0两种版本的协议进行对比。可以直观的感受到,http/2.0比http/1.0快出5倍左右的速度。

考虑到您可能需要分别用开发者工具仔细查看下两个版本,我已经帮你找好了两个版本对应的链接。(不客气)


那http/2.0究竟引入了哪些机制、特性才达到目前的加速效果呢?简答的说可以概括成。

  • 二进制分帧层
  • 多路复用
  • 首部压缩
  • 服务器推送(server push)

    二进制分帧层与多路复用

    引入了二进制分帧层,就不再是文本传输了,而是数据帧(二进制)。
    注意:http原本的语义,方法、动词、首部都不受影响。仅仅是传输期间的数据格式变化了。

前端与HTTP

http/2规定了10种不同的帧。
如上图,分针层会把 开始行首部行分割到headers帧正文实体分割到data帧。


tcp 连接在客户端和服务器间建立了一条运输的通道,可以双向通行,当一端要向另一端发送消息时,会先把这个消息拆分成几部分(帧),然后通过发起一个流对这些帧进行发送,最后在另一端将同一个流的帧重新组合。

这里涉及了以下概念。

流:已建立的连接上的双向字节流
消息:与逻辑消息对应的完整的一系列数据帧
帧:http/2 通信的最小单位,每个帧包含帧首部

前端与HTTP

其中帧对数据进行顺序标识,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的传输数据,这就是流所做的事情。

http/2对同一域名下所有请求都是基于流,也就是说同一域名不管访问多少文件,也只建立一路连接。同样apache的最大连接数为300,因为有了这个新特性,最大的并发就可以提升到300,比原来提升了6倍!

首部压缩

在服务器和客户端各维护一个“首部表”,表中用索引代表首部名,或者首部键 - 值对,上一次发送两端都会记住已发送过哪些首部,下一次发送只需要传输差异的数据,相同的数据直接用索引表示即可。

前端与HTTP

首部压缩,可以解决http头臃肿的问题。

服务器推送(server push)

服务器可以对一个客户端请求发送多个响应。也就是说,除了对最初请求的响应外,服务器还可以额外向客户端推送资源。

这里就涉及到了另一个帧类型:push_promise帧。
举个栗子,当客户端请求index.html时,服务器会同时推送style.css,index.js对应的push_promise帧。客户端可以直接缓存起来。

基于http/2对前端性能优化的思考

个人觉得前端的性能优化,应该主要从两个方面。加载速度流畅运行
原引,在网上看到的一段话:

网页不仅应该被快速加载,同时还应该流畅运行,比如快速响应的交互,如丝般顺滑的动画等。


http/1.x的优化方案

当然,今天的主题是讨论网路协议,那我们只谈加载速度。
基于http1.x的相关特性,可爱的前端们提出了很多颇具成效的优化方案。(精灵图,多域名加载等等)其中,比较著名的雅虎军规,很多人应道都知道,这里有一张整理好的图。

前端与HTTP

http/2的变革

在http/2的基础上,很多http/1.x要优化的问题,都不存在了。问题都不存在了,问题的优化方案也就不存在了。
这里插一句,我始终坚信的一个观点是:没有任何优化手段是不需要付出代价的。是药三分毒,无非是取舍罢了。

1.合并css、js与精灵图

在http/1.x时代,http并没有最大程度上利用好tcp链接。虽然http/1.1里有了http管道,但其也带来了队首阻塞等问题,同时也要受队列大小的限制。所以我们要通过合并文件的方式减少http链接数量。
不错,减少http请求数量的确能起到优化的作用,但与此同时,也有很多弊端:

  1. 所有文件合成一个大文件,那不管哪个模块发生变更,都要整体更新,用户都要重新下载,无法继续使用缓存。
  2. 带来了额外的维护成本。印象比较深的是维护精灵图,稍微改一点,就得重新弄。

以上,就是”合并css方案"、“合并js方案”、“精灵图方案”的优势与弊端。

  • 在http/1.x基础上,明显优势>弊端,所以我们使用这些方案。
  • 但http/2,它对tcp链接的利用程度已经有了飞跃性的提升。此时这些方案是否优势>弊端,就值得商榷了。笔者觉得应该正好反过来。优势<弊端

2.分域名

在http/1.x基础上,分域名有两个好处。

  • 为了绕过浏览器对同一域名的最大管道限制。可以同时请求更多内容。
  • 同一域名下的请求报文,会匹配的站点的全部cookie,增大请求报文长度。而很多资源,比如图片、css是不需要cookie的。

在http/2上,对于这些问题

  • 原本就支持多路复用,没必要分
  • 首部压缩机制,首部行大点,也就传一个。

3.接口合并

如果页面需要多种数据,我们会尽量将数据汇总到一个接口,以减少http请求数量。
这种做法,几乎违背了各种程序设计规范,比如“单一职责原则”等等,接口很难复用,维护成本高。
这种方案在http/2下,明显弊端>优势了。

参考文献