HTTP优化

HTTP 的相关优化主要包括持久连接 Keep-Alive、修改时间 Last-Modified 以及 If-Modified-Since、版本标记 ETag 以及 If-None-Match、缓存时间 Expires 以及 Cache-Control 和 gzip 压缩等。

持久连接Keep-Alive

HTTP 连接设计之初是请求-响应-关闭,也就是每建立一次 HTTP 连接,只能进行一次资源请求,当需要在同一目标服务器上获取多个资源的时候,就需要多次建立 HTTP 连接,而这个多次建立连接的过程,便降低了网站的性能。

于是,出现了 Connection:Keep-Alive,人称持久连接。Keep-Alive 避免了建立或者说重新建立连接的过程,减少了 HTTP 连接。而与此配套的有 Keep-Alive:timeout=120,max=5

其中,timeout=120 是指这个 TCP 通道保持 120S,max=5 指这个 TCP 通道最多接收 5 个 HTTP 请求,之后便自动关闭该连接。

修改时间Last-Modified和If-Modified-Since

Last-Modified 首部是服务端对客户端的 HTTP 响应所加的一个与缓存有关的 HTTP 首部,该首部标记了所请求资源在服务端的最后修改时间。类似:

Last-Modified : Fri , 12 May 2015 13:10:33 GMT

当客户端发现 HTTP 响应头中有 Last-Modified,会对资源进行缓存,在下次请求资源时,在 HTTP 请求头中添加 If-Modified-Since 首部,首部中将会添加上次成功请求资源时响应头部的 Last-Modified 属性值,即:

If-Modified-Since : Fri , 12 May 2015 13:10:33 GMT

当服务端接收到的 HTTP 请求中,发现有 If-Modified-Since 头部时,会将该属性值与请求资源的最后修改时间进行比对,如果最后修改时间与该属性值一致时,服务端会返回一个 304 Not Modified 响应,该响应中不包括响应实体。浏览器收到 304 的响应后,会进行重定向,获取本地缓存资源。如果最后修改时间与该属性值不一致,则会从服务端重新获取资源,做出 200 响应。

版本标记ETag和If-None-Match

ETag 其实与 Last-Modified 是差不多的方式,但是 ETag 并没有选择以时间作为标记,而是对所请求文件进行某些算法来生成一串唯一的字符串,作为对某一文件的标记。当收到客户端对某一资源的请求时,服务端在响应时,添加 ETag 首部,如下:

ETag:W/"a627ff1c9e65d2dede2efe0dd25efb8c"

当客户端发现 ETag 头部时,同样会对资源进行缓存,并在下次请求时,在请求头部添加 If-None-Match,如:

If-None-Match:W/"a627ff1c9e65d2dede2efe0dd25efb8c"

当服务端收到请求中含有该头部时,会使用同样的 ETag 生成算法对文件 ETag 进行计算,并与 If-None-Match 属性值进行比对,如果一致,则返回一个 304 Not Modified 响应,基本与上一种方式是一致的。

缓存时间Expires和Cache-Control

上述两种方式中,每次请求资源时,虽然在有缓存的情况下,选择缓存进行渲染绘制,但是在这之前还是发起了一次 HTTP 请求,虽然并没有真实的响应实体,但是依然会造成一些资源消耗。而 Expires 与上述两种方式使用了不同的思路。

当服务端希望客户端浏览器对某一资源进行缓存时,为了免去客户端每次都要询问自己:我上次的缓存现在还能用吗?所以,服务端选择了放权。只去告诉浏览器,我这次给你的资源你可以用多长时间,在这个时间段内,你可以一直使用它,无需每次咨询我。而服务端就是通过 Expires 属性来告诉客户端浏览器可以多长时间内不需要询问服务端。如下:

Expires:Thu, 19 Nov 2021 15:00:00 GMT

当客户端在响应首部中发现该属性值时,便会将该资源缓存起来,而缓存的过期时间即是 Expires 中的时间。在这个时间段内,浏览器完全自主。

但是,Expires 有一个不足的地方是,如果服务端时间与客户端本地时间不统一时,可能服务端让客户端可以对该资源缓存一个小时,而客户端本地时间比服务端时间快了两个小时,那就意味着,所有缓存都将不会生效。

于是有了弥补该不足的一个属性,即:Cache-Control。如果服务端在响应首部添加该属性时,客户端将直接使用该属性值来生成本地时间的缓存过期时间,这样便解决了这个问题,如下:

Cache-Control:max-age=3600

如果客户端在 2021 年 5 月 01 日 13 时 00 分 00 秒收到该响应时,便会加上 3600 秒也就是 2021 年 5 月 01 日 14 时 00 分 00 秒作为缓存过期时间。如果响应头部既有 Expires 和 Cache-Control,浏览器会首选 Cache-Control。

压缩gzip

开启 HTTP 的压缩 gzip,可以大大减少传输的数据包的大小:

Accept-Encoding: gzip, deflate, br

通过 Accept-Encoding 指定压缩方式。