浏览器缓存控制
浏览器缓存控制
Last-Modified/ If-Modified-Since(Validation)
在浏览器第一次请求某一个URL时,服务器端的返回状态码200,内容是客户端请求的资源,同时有一个Last-Modified的属性标记此文件在服务器端最后被修改的时间。
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头,询问该时间之后文件是否有被修改过:
If-Modified-Since : Fri , 12 May 2006 18:53:33 GMT
如果服务器端的资源没有变化,则自动返回 304(Not Changed.)状态码,内容为空,这样就节省了传输数据量。
当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
Last-Modified的问题
1、一些文件会被编辑,但内容并未改变,这个时候不希望客户端认为这个文件被修改了,而重新获取资源。
2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,If-Modified-Since无法检查到。
3、某些服务器不能精确的得到文件的最后修改时间。
Expires(Freshness)
Expires用来控制缓存失效的日期。当浏览器看到响应中有一个Expires头时,它会和相应的组件一起保存到其缓存中,只要组件没有过期,浏览器就会使用缓存版本而不会进行任何的HTTP请求。长久的Expires头适用于图片等不经常更新的资源。Expires设置的日期格式必须为GMT(格林尼治标准时间)。Expires既适用于 HTTP1.0,也适用于 HTTP1.1。
Expires:Wed, 11 Jan 2017 08:10:26 GMT
因为请求根本没有产生,所以在chrome下请求头部会显示:Provisional headers are shown。状态码为 200 OK (from cache) 。
Expires的不足:
首先,Expires头使用的是一个特定的时间,要求客户端和服务器端的时钟严格同步。如果服务器和客户端的时间不统一,这有可能出现缓存提前失效的情况,存在不稳定性。其次,假如Expires的日期到来,需要在服务器配置中再提供一个新的日期。
Cache-Control(Freshness)
HTTP1.1引入了Cache-Control头来克服Expires头的不足。Cache-Control使用max-age制定组件被缓存多久,以秒为单位。例如
Cache-Control:max-age=3600表示组件将被缓存60分钟。
如果max-age和Expires同时出现,则max-age有更高的优先级,浏览器会根据max-age的时间来确认缓存过期时间。若缓存新鲜,则不发送请求直接使用缓存。
常用 cache-directive 值 |
|
Cache-directive |
说明 |
public |
所有内容都将被缓存(客户端和代理服务器都可缓存) |
private |
内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存),默认值 |
no-cache |
do-not-serve-from-cache-without-revalidation:可以被缓存,但是在与服务器进行验证之前不能供客户端使用。如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存,如果资源未被更改,可以直接使用。 |
no-store |
所有内容都不会被缓存到缓存或 Internet 临时文件中 |
must-revalidation/proxy-revalidation |
如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证 |
max-age=xxx (xxx is numeric) |
缓存内容的有效时间长度,将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用。如果和Last-Modified并存时, 优先级更高。值为0时每次都从服务器获取资源。 |
浏览器的不同操作 |
|
打开新窗口 |
如果指定cache-control的值为private、no-cache、must-revalidate,那么打开新窗口访问时都会重新访问服务器。而如果指定了max-age值,那么在此值内的时间里就不会重新访问服务器,例如:Cache-control: max-age=5 表示当访问此网页后的5秒内不会去再次访问服务器. |
在地址栏回车 |
如果值为private或must-revalidate,则只有第一次访问时会访问服务器,以后就不再访问。如果值为no-cache,那么每次都会访问。如果值为max-age,则在过期之前不会重复访问。 |
按后退按扭 |
如果值为private、must-revalidate、max-age,则不会重访问,而如果为no-cache,则每次都重复访问. |
按刷新按扭 |
无论为何值,都会重复访问. |
Etag(Entity Tag)(Validation)
服务器在检测缓存的组件是否和原始服务器上的组件匹配时有两种方法:
(1)比较最近修改日期;Last-Modified/If-Modified-since
(1)比较实体标签;Etag/If-None-Match(优先级比If-Modified-since高)
实体标签,是web服务器和浏览器用于确认缓存组件的有效性的一种机制。
ETag:"50b1c1d4f775c61:df3"
第一次请求时:
1.客户端发起HTTP GET 请求一个资源;
2.服务器处理请求,返回资源,包括Http Etag和状态码200
第二次请求时:
1.客户端发起 HTTP GET 请求一个文件,请求中包括一个If-None-Match头,内容就是第一次请求时服务器返回的Etag的值
2.服务器判断接受到的Etag和计算出来的Etag是否匹配。若匹配,返回304状态码,客户端继续使用本地的缓存。若不匹配,返回资源和新的ETag。
ETag带来的问题
ETag通常使用组件的某些属性来构造它,这些属性对于特定的寄宿了网站服务器来说是唯一的。当浏览器从一台服务器上获取了原始组件,之后又向另外一台不同的服务器发起条件GET请求时,ETag是不会匹配的。
对组件进行不必要的重新加载还会影响服务器的性能并增加带宽开销。如果你的RoundRobin Rotation集群中有n台服务器,下一次用户缓存中的Etag能和服务器匹配的概率是1/n。Etag还会降低代理缓存的效率,因为代理的与自身的不匹配会重新下载。
HTTP响应优化
目前的Web服务器绝大多数都采用HTTP/1.1标准,所以移除ETag和Expires,使用Cache-Control控制本地缓存。
post请求不能缓存。