再谈web缓存

缓存类型

​ web缓存主要分为服务端侧的缓存(如Nginx和Apache)和客户端的缓存(浏览器)。

​ 这里我们主要讨论的是浏览器缓存,其主要分为强缓存和协议缓存两个类:

  • 强缓存:浏览器在加载资源的时候,会首先根据http header来判断这个请求是否命中自己的缓存,如果可以命中,就直接从自己的缓存中读取这个资源,而不会再向服务器发送请求。

  • 协议缓存:如果强缓存没有命中的时候,浏览器就会发送一个请求到服务器上,此时服务器就会听过判断http header来判断这个请求是否命中协议缓存。如果命中,浏览器就会将这个请求返回(返回码304),这里不会返回请求的资源,而是告诉浏览器直接从缓存中去加载这个资源。若没有命中,就会将资源返回,冰球更新本地缓存,此时的状态码是200

    这里需要强调的是,强缓存和协议缓存的最大区别就是是否向服务器发送了请求。强缓存是不会发请求到服务器的,直接在浏览器中进行处理,但是协议缓存会向服务器中发送请求

缓存的设置

HTTP meta标签设置缓存

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

​ 通过meta标签来设置缓存,告诉浏览器只能通过发送请求的方式请求资源,不缓存当前页面。但是这种方式的缺点在于浏览器的兼容性不强,且由于代理服务器不能解析HTML代码,所以这段代码不能在代理服务器上运行。

HTTP头部信息的缓存设置

Expires

​ Expires是一种强缓存,是HTTP1.0中提出的一种缓存标准,由服务器返回一个绝对时间,用GMT字符串的格式返回。如:Expires:Thu, 31 Dec 2016 23:55:55 GMT,读取缓存的条件是:服务器的缓存过期时间 < 客户端的当前时间。

​ 很明显,这种方式有一个明显的缺陷就是如果服务器的当前时间和客户端的当前时间相差较大,比如牵扯到跨时区等问题,这种方式明显是不可取的,采用的另一种方式就是HTTP1.1标准中的Cache-Control:max-age=?来代替

Cache-Control

​ 使用Cache-Control描述一个相对时间,在进行缓存处理的时候,都是采用客户端的时间进行判断。因此这个机制相较于Expires更加准确有效。

​ Cache-Control可取的值有下面几种,含义如下:

  • Public指示响应可被任何缓存区缓存。
  • Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当前用户的部分响应消息,此响应消息对于其他用户的请求无效。
  • no-cache指示请求或响应消息不能缓存,该选项并不是说可以设置”不缓存“,而是需要和服务器确认
  • no-store在请求消息中发送将使得请求和响应消息都不使用缓存,完全不存下來。
  • max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。上次缓存时间(客户端的)+max-age(64200s)<客户端当前时间
  • min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
  • max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
Last-Modified和If-Modified-Since

​ Last-Modified表示的是这个资源的最后修改时间,If-Modified-Since代表的是资源过期后(强缓存失效),如果该资源具有If-Modified-Since这个特性,那么在向web服务器发送请求的时候就会携带If-Modified-Since表示请求时间。web服务器在收到请求之后发现If-Modified-Since就会将请求资源的时间和资源修改的最后时间进行对比。如果这段时间内资源发生了修改,就会将这个资源整体全部返回,HTTP状态码返回的是200,如果这段时间没有发生修改,就会返回HTTP 304,告诉浏览器继续使用缓存。

​ 同时这种方式也明显有个缺点,就是某些文件会定期生成,有时候虽然文件的内容并没有发生改变,但是Last-Modified却改变了,这样就会导致文件的缓存没办法使用,从而出现服务器中没有获取文件的准确修改时间等无法使用缓存的现象。

​ 并且,这种方式的Last-Modified标注修改只能精确到秒级,如果有一个文件在一秒之内被修改了很多次的话,就会导致不能准确修改文件的修改时间问题,无法即使的修改文件。

Etag和If-None-Match

​ HTTP1.1中的Etag/If-None-Match解决了上面Last-Modified的一些问题。同时他们也需要配合Cache-Control使用。其机制和Cache-Control相似,不过,Etag是服务器自动生成或由开发者生成的资源在服务器中的唯一标识符,可以更加准确的控制缓存。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。

以上过程总结成流程图如下所示:

1)当浏览器第一次请求的时候:

你想要输入的替代文字

2)浏览器再次请求的时候:

你想要输入的替代文字

同时,以上提到的各种缓存机制还和用户的行为有关,具体如下所示:

你想要输入的替代文字

0%