本篇主要讲解浏览器的缓存机制和CDN的缓存机制。
我们在打开浏览器访问一个页面的时候,通常有两个头来控制文件的缓存过期时间,一个是 Expires,一个是 Cache-Control,不过 Expires 是 HTTP/1.0 标准的东西,目前主流的都是 HTTP/1.1 。所以重点将下 Cache-Control。
如果同时有 Expires 和Cache-Control,Cache-control 的优先级要高于 Expires。
Cache-Control
Cache-Control的值可以为:public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。
指令含义如下:
- Public:指示响应可被任何缓存区缓存。
- Private:指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
- no-cache:指示请求或响应消息不能缓存
- no-store:用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
- max-age:指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
- min-fresh:指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
- max-stale:指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
如上图所示,同时有:
- expires:Sun, 03 Sep 2017 02:59:56 GMT
- cache-control:public, must-revalidate, max-age=1036800
则 cache-control的优先级高与expires,其表示该图片文件缓存时间为1036800秒后过期
Last-Modified/If-Modified-Since
Last-Modified/If-Modified-Since要配合Cache-Control使用。
- Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。
- If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache。
Etag/If-None-Match
Etag/If-None-Match也要配合Cache-Control使用。
- Etag:web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识,Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。
- If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match (Etag的值)。web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200或304。
如上图所示的
- etag:”4BEB88555ABD8D7F519606884054A5AE”
在又拍云etag其实就是文件的md5,但是缩略图除外,因为缩略图是动态生成的
为什么有Last-Modified还要 Etag?
HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
- Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间
- 如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存
- 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形
- Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。
age
age 字段表示文件在服务器缓存的时间,单位是秒。Age消息头的值通常接近于0。表示此消息对象刚刚从原始服务器获取不久;其他的值则是表示代理服务器当前的系统时间与此应答消息中的通用消息头 Date 的值之差。
参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Age
用户行为与缓存
浏览器缓存行为还有用户的行为有关!!!
用户行为 | Expires/Cache-Control | Last-Modified/Etag |
---|---|---|
地址栏输入回车 | 有效 | 有效 |
页面链接跳转 | 有效 | 有效 |
新开窗口 | 有效 | 有效 |
前进·后退 | 有效 | 有效 |
F5 刷新 | 无效 | 有效 |
Ctrl+F5刷新 | 无效 | 无效 |
浏览器的请求过程
http缓存是基于HTTP协议的浏览器文件级缓存机制。即针对文件的重复请求情况下,浏览器可以根据协议头判断从服务器端请求文件还是从本地读取文件,chrome控制台下的Frames即展示的是浏览器的http文件级缓存。以下是浏览器缓存的整个机制流程。主要是针对重复的http请求,在有缓存的情况下判断过程主要分3步:
判断expires,如果未过期,直接读取http缓存文件,不发http请求,否则进入下一步
判断是否含有etag,有则带上if-none-match发送请求,未修改返回304,修改返回200,否则进入下一步
判断是否含有last-modified,有则带上if-modified-since发送请求,无效返回200,有效返回304,否则直接向服务器请求
第一次请求
浏览器再次请求
参考:《HTTP权威指南》
web 服务器配置
以nginx 为例,参考官网Module ngx_http_headers_module 配置