原文: http://cncc.bingj.com/cache.aspx?q=max-age+expires+Last-Modified&d=4997458151473641&mkt=en-US&setlang=en-US&w=obLC-DXYkHDglJJNfr5xl1yTc4LW9a_ocss
本文着重论述了关于 HTTP 缓存头部的重要信息,以及有关的 CDN 行为。假如你正在寻找现代 web 中 HTTP cache headers 的深刻信息,这里有你所需的一切。
主要经过新鲜度和有效性,来决定对资源的缓存。若是一个有效的资源没有改变过,不多会再次发送完整的资源,此时缓存中的一个新鲜的副本是当即可用的。假设没有校验器(如 ETag/Last-modified 头部),而且缺乏明确的新鲜度信息的话,那就要常常(但并不老是)被认定为没法缓存了。如今把焦点转移到须要被考虑到的几种 HTTP 头部上:web
不须要服务器通讯的请求被认为是最佳的请求:使用响应的本地副本,既能够消除网络延迟,又能避免数据传输带来的网络负载。HTTP 规范容许服务器发送多个不一样的 Cache-Control 指令,用以控制身处诸如CDN的中间人缓存中,浏览器如何(以及什么时候)缓存个别的响应:
数据库
Cache-control: private, max-age=0, no-cache复制代码
这些设置项被称为响应指令,以下所示:浏览器
被标记为 `public` 的响应,即使在其关联了一个 HTTP 认证或其 HTTP 响应状态码一般不可缓存的状况下,也均可以被缓存。在大多数状况下,标记 `public` 不是必要的,由于明确的缓存信息(如 `max-age`)已经表示响应是可缓存的。
缓存
反之,被标记为`private`的响应,能够被(浏览器)缓存,可是这样的响应是典型地面向单个用户的,所以不能被中间人缓存(好比含有用户私人信息的 HTML 页面能够被用户的浏览器缓存而非 CDN)。
bash
`no-cache`表示在检查过服务器响应是否已经改变以前,返回的响应不能被用于随后向同一 URL 的请求。若是一个适当的 Etag (校验记号) 做为一个结果出现,`no-cache`就会引起一次往返动做以试图校验已缓存过的响应。若是资源未改变过,缓存就会避免下载行为。换句话说,web 浏览器可能会缓存资源,但不得不在每次请求都检查资源是否已改变(未改变则返回 304)。
服务器
与之相反的是,`no-store`更简单些。这样说是由于它禁止浏览器和全部中间人从返回的响应中缓存任何版本的资源,例如响应中包含隐私/我的的信息或银行数据等。用户每次请求这个资源都是请求服务器,每次资源都要被下载。
网络
`max-age` 指令表示获取到的资源被容许重复使用的最长时间,以秒为单位(从请求发起的时刻算起)。举例来讲,`max-age=90`指示了资源在以后的 90 秒钟可被重用(保存在浏览器缓存中)。
并发
`s-`表明`shard cache`。这个指令是明确针对中间人缓存中的 CDN 的。当这个指令出如今头部中时,会覆盖掉 `max-age` 和 `expires` 的设置。app
`Cache-Control` 是做为 HTTP/1.1 标准的一部分定义的,用来接替以前的头部信息(如 `expires`)来规定响应的缓存策略。 `Cache-Control` 被全部现代浏览器支持,实乃咱们必备的。
旧的 `pragma` 头部承担了许多工做,其中大部分都有了更新的实现。咱们通常将cache-control: no-cache
视为pragma: no-cache
的更新一些的实现。在总体的理解上了解这个指令是有必要的,但从此不会再为其定义新的 HTTP 指令了。
几年前,这是指定资源有效期的主要途径。Expires 只是个基本的 date-time 时间戳,对那些游走在不规范地带的用户代理来讲,仍是至关管用的;而对于现代系统,则是优先使用cache-control
头部,设置max-age
和s-maxage
等。为了兼容的目的,在此设置匹配的值是个好的作法;一样重要的是确保日期的格式正确,否则会被认为过时。
Expires: Sun, 03 May 2015 23:02:37 GMT复制代码
为了不破坏规范,不要设置超过一年的日期值。(译注:规范中的说明为 -- To mark a response as "never expires," an origin server sends an Expires date approximately one year from the time the response is sent. HTTP/1.1 servers SHOULD NOT send Expires dates more than one year in the future. )
这种在 HTTP/1.1 中定义的有效性 token:
这个例子将展现其做用:在首次获取一个资源 90 秒后,发起一次新的浏览器请求(彻底同样的资源);浏览器寻找本地缓存,当找到上一次缓存的请求后并发现其过时时,就会从服务器请求完整的内容 -- 问题是,若是资源没有改变过,在其已存在于 CDN 缓存的状况下,绝无理由再下载一遍。
有效性 token 正是用来解决此类问题。边缘服务器(edge server, 译注:如专门负责缓存、防火墙、负载均衡等的第一层服务器;其后是提供web服务的第二层和提供数据库的第三层)建立并返回特制的 token,存放在 ETag 头部域中,做为既有文件的指纹信息,通常用一个 hash 值来表示。客户端不须要知道该 token 如何产生,只肖在随后的请求中携带之即可。若是 token 相同,也就意味着资源没变,这样一来也就跳过了从新下载。
web 浏览器自动提供了“If-None-Match” 请求头,用来包含 ETag token;服务器将根据此 token 比对缓存中的当前资源。若是缓存中的资源未发生变化,浏览器将收到一个 `304 Not Modified` 的响应,有效性续期 90 秒。特别是由于不用从新下载资源,带宽和时间都被节省了。
浏览器为 web 开发者承担了大多数工做。好比,浏览器自动检测到前一次指定的有效性 token ,将其附加到随后的请求中,并按需基于服务器响应更新缓存的时间戳。web 开发者所以只须要确保服务器提供所需的 ETag token 就好了。
`Last-Modified` 头部做为一个常见的校验器,指示了文件最后一次改变的时间。能够将其视为一个 HTTP/1.0 时代遗留的校验器。当缓存保存了一个包含此头部的资源时,能够利用其查询服务器资源是否已超时(从资源上次被使用时)。相应的请求头部为 `If-Modified-Since`。
一个 HTTP/1.1 的源服务器应该同时发送 ETag 和 Last-Modified。更多细节能够在 RFC2616 规范中找到。
一个例子:
HTTP/1.1 200 OK
Server: keycdn-engine
Date: Mon, 27 Apr 2015 18:54:37 GMT
Content-Type: text/css
Content-Length: 44660
Connection: keep-alive
Vary: Accept-Encoding
Last-Modified: Mon, 08 Dec 2014 19:23:51 GMT
ETag: "5485fac7-ae74"
Cache-Control: max-age=533280
Expires: Sun, 03 May 2015 23:02:37 GMT
X-Cache: HIT
X-Edge-Location: defr
Access-Control-Allow-Origin: *
Accept-Ranges: bytes复制代码
Cache-Control 和 ETag 头部域是用来控制资源新鲜度和有效性的现代机制。其余值则“仅仅”用来向后兼容。
----------------------------------------