问你一句:「你知道 HTTP/1.1 该如何优化吗?」php
我想你第一时间想到的是,使用 KeepAlive 将 HTTP/1.1 从短链接改为长连接。css
这个确实是一个优化的手段,它是从底层的传输层这一方向入手的,经过减小 TCP 链接创建和断开的次数,来减小了网络传输的延迟,从而提升 HTTP/1.1 协议的传输效率。html
但其实还能够从其余方向来优化 HTTP/1.1 协议,好比有以下 3 种优化思路:webpack
下面,就针对这三种思路具体看看有哪些优化方法。git
这个思路你看到是否是以为很奇怪,不发送 HTTP 请求,那还客户端还怎么和服务器交互数据?小林你这不是耍流氓嘛?程序员
冷静冷静,你说的没错,客户端固然要向服务器发送请求的。github
可是,对于一些具备重复性的 HTTP 请求,好比每次请求获得的数据都同样的,咱们能够把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,没必要在经过网络获取服务器的响应了,这样的话 HTTP/1.1 的性能确定肉眼可见的提高。web
因此,避免发送 HTTP 请求的方法就是经过缓存技术,HTTP 设计者早在以前就考虑到了这点,所以 HTTP 协议的头部有很多是针对缓存的字段。算法
那缓存是如何作到的呢?apache
客户端会把第一次请求以及响应的数据保存在本地磁盘上,其中将请求的 URL 做为 key,而响应做为 value,二者造成映射关系。
这样当后续发起相同的请求时,就能够先在本地磁盘上经过 key 查到对应的 value,也就是响应,若是找到了,就直接从本地读取该响应。毋庸置疑,读取本次磁盘的速度确定比网络请求快得多,以下图:
聪明的你可能想到了,万一缓存的响应不是最新的,而客户端并不知情,那么该怎么办呢?
放心,这个问题 HTTP 设计者早已考虑到。
因此,服务器在发送 HTTP 响应时,会估算一个过时的时间,并把这个信息放到响应头部中,这样客户端在查看响应头部的信息时,一旦发现缓存的响应是过时的,则就会从新发送网络请求。HTTP 关于缓说明会的头部字段不少,这部份内容留在下次文章,此次暂时不具体说明。
若是客户端从第一次请求获得的响应头部中发现该响应过时了,客户端从新发送请求,假设服务器上的资源并无变动,仍是老样子,那么你以为还要在服务器的响应带上这个资源吗?
很显然不带的话,能够提升 HTTP 协议的性能,那具体如何作到呢?
只须要客户端在从新发送请求时,在请求的 Etag
头部带上第一次请求的响应头部中的摘要,这个摘要是惟一标识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要作个比较。
若是不一样,那么说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。
若是相同,说明客户端的缓存仍是能够继续使用的,那么服务器仅返回不含有包体的 304 Not Modified
响应,告诉客户端仍然有效,这样就能够减小响应资源在网络中传输的延时,以下图:
缓存真的是性能优化的一把万能钥匙,小到 CPU Cache、Page Cache、Redis Cache,大到 HTTP 协议的缓存。
减小 HTTP 请求次数天然也就提高了 HTTP 性能,能够从这 3 个方面入手:
咱们先来看看什么是重定向请求?
服务器上的一个资源可能因为迁移、维护等缘由从 url1 移至 url2 后,而客户端不知情,它仍是继续请求 url1,这时服务器不能粗暴地返回错误,而是经过 302
响应码和 Location
头部,告诉客户端该资源已经迁移至 url2 了,因而客户端须要再发送 url2 请求以得到服务器的资源。
那么,若是重定向请求越多,那么客户端就要屡次发起 HTTP 请求,每一次的 HTTP 请求都得通过网络,这无疑会越下降网络性能。
另外,服务端这一方每每不仅有一台服务器,好比源服务器上一级是代理服务器,而后代理服务器才与客户端通讯,这时客户端重定向就会致使客户端与代理服务器之间须要 2 次消息传递,以下图:
若是重定向的工做交由代理服务器完成,就能减小 HTTP 请求次数了,以下图:
并且当代理服务器知晓了重定向规则后,能够进一步减小消息传递次数,以下图:
除了 302
重定向响应码,还有其余一些重定向的响应码,你能够从下图看到:
其中,301
和 308
响应码是告诉客户端能够将重定向响应缓存到本地磁盘,以后客户端就自动用 url2 替代 url1 访问服务器的资源。
若是把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源仍是同样,可是减小请求,也就意味着减小了重复发送的 HTTP 头部。
另外因为 HTTP/1.1 是请求响应模型,若是第一个发送的请求,未收到对应的响应,那么后续的请求就不会发送,因而为了防止单个请求的阻塞,因此通常浏览器会同时发起 5-6 个请求,每个请求都是不一样的 TCP 链接,那么若是合并了请求,也就会减小 TCP 链接的数量,于是省去了 TCP 握手和慢启动过程耗费的时间。
接下来,具体看看合并请求的几种方式。
有的网页会含有不少小图片、小图标,有多少个小图片,客户端就要发起多少次请求。那么对于这些小图片,咱们能够考虑使用 CSS Image Sprites
技术把它们合成一个大图片,这样浏览器就能够用一次请求得到一个大图片,而后再根据 CSS 数据把大图片切割成多张小图片。
这种方式就是经过将多个小图片合并成一个大图片来减小 HTTP 请求的次数,以减小 HTTP 请求的次数,从而减小网络的开销。
除了将小图片合并成大图片的方式,还有服务端使用 webpack
等打包工具将 js、css 等资源合并打包成大文件,也是能达到相似的效果。
另外,还能够将图片的二进制数据用 base64
编码后,以 URL 的形式潜入到 HTML 文件,跟随 HTML 文件一并发送.
<image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAFKCAIAAAC7M9WrAAAACXBIWXMAA ... />
这样客户端收到 HTML 后,就能够直接解码出数据,而后直接显示图片,就不用再发起图片相关的请求,这样便减小了请求的次数。
能够看到,合并请求的方式就是合并资源,以一个大资源的请求替换多个小资源的请求。
可是这样的合并请求会带来新的问题,当大资源中的某一个小资源发生变化后,客户端必须从新下载整个完整的大资源文件,这显然带来了额外的网络消耗。
不要一口气吃成大胖子,通常 HTML 里会含有不少 HTTP 的 URL,当前不须要的资源,咱们不必也获取过来,因而能够经过「按需获取」的方式,来减小第一时间的 HTTP 请求次数。
请求网页的时候,不必把所有资源都获取到,而是只获取当前用户所看到的页面资源,当用户向下滑动页面的时候,再向服务器获取接下来的资源,这样就达到了延迟发送请求的效果。
对于 HTTP 的请求和响应,一般 HTTP 的响应的数据大小会比较大,也就是服务器返回的资源会比较大。
因而,咱们能够考虑对响应的资源进行压缩,这样就能够减小响应的数据大小,从而提升网络传输的效率。
压缩的方式通常分为 2 种,分别是:
无损压缩是指资源通过压缩后,信息不被破坏,还能彻底恢复到压缩前的原样,适合用在文本文件、程序可执行文件、程序源代码。
首先,咱们针对代码的语法规则进行压缩,由于一般代码文件都有不少换行符或者空格,这些是为了帮助程序员更好的阅读,可是机器执行时并不要这些符,把这些多余的符号给去除掉。
接下来,就是无损压缩了,须要对原始资源创建统计模型,利用这个统计模型,将常出现的数据用较短的二进制比特序列表示,将不常出现的数据用较长的二进制比特序列表示,生成二进制比特序列通常是「霍夫曼编码」算法。
gzip 就是比较常见的无损压缩。客户端支持的压缩算法,会在 HTTP 请求中经过头部中的 Accept-Encoding
字段告诉服务器:
Accept-Encoding: gzip, deflate, br
服务器收到后,会从中选择一个服务器支持的或者合适的压缩算法,而后使用此压缩算法对响应资源进行压缩,最后经过响应头部中的 content-encoding
字段告诉客户端该资源使用的压缩算法。
content-encoding: gzip
gzip 的压缩效率相比 Google 推出的 Brotli 算法仍是差点意思,也就是上文中的 br,因此若是能够,服务器应该选择压缩效率更高的 br 压缩算法。
与无损压缩相对的就是有损压缩,通过此方法压缩,解压的数据会与原始数据不一样可是很是接近。
有损压缩主要将次要的数据舍弃,牺牲一些质量来减小数据量、提升压缩比,这种方法常常用于压缩多媒体数据,好比音频、视频、图片。
能够经过 HTTP 请求头部中的 Accept
字段里的「 q 质量因子」,告诉服务器指望的资源质量。
Accept: audio/*; q=0.2, audio/basic
关于图片的压缩,目前压缩比较高的是 Google 推出的 WebP 格式,它与常见的 Png 格式图片的压缩比例对好比下图:
能够发现,相同图片质量下,WebP 格式的图片大小都比 Png 格式的图片小,因此对于大量图片的网站,能够考虑使用 WebP 格式的图片,这将大幅度提高网络传输的性能。
关于音视频的压缩,音视频主要是动态的,每一个帧都有时序的关系,一般时间连续的帧之间的变化是很小的。
好比,一个在看书的视频,画面一般只有人物的手和书桌上的书是会有变化的,而其余地方一般都是静态的,因而只须要在一个静态的关键帧,使用增量数据来表达后续的帧,这样便减小了不少数据,提升了网络传输的性能。对于视频常见的编码格式有 H26四、H265 等,音频常见的编码格式有 AAC、AC3。
此次主要从 3 个方面介绍了优化 HTTP/1.1 协议的思路。
第一个思路是,经过缓存技术来避免发送 HTTP 请求。客户端收到第一个请求的响应后,能够将其缓存在本地磁盘,下次请求的时候,若是缓存没过时,就直接读取本地缓存的响应数据。若是缓存过时,客户端发送请求的时候带上响应数据的摘要,服务器比对后发现资源没有变化,就发出不带包体的 304 响应,告诉客户端缓存的响应仍然有效。
第二个思路是,减小 HTTP 请求的次数,有如下的方法:
第三思路是,经过压缩响应资源,下降传输资源的大小,从而提升传输效率,因此应当选择更优秀的压缩算法。
无论怎么优化 HTTP/1.1 协议都是有限的,否则也不会出现 HTTP/2 和 HTTP/3 协议,后续咱们再来介绍 HTTP/2 和 HTTP/3 协议。
好了,这次分享到这就结束了,若是这篇文章对你有帮助,欢迎来个三连,大家的支持就是小林的最大动力,咱们下次见!