认识缓存之客户端缓存
缓存的最后一层,是直接面对客户端的客户端缓存。通常也把这部分称为web缓存。web缓存位于客户端。缓存会根据进来的请求保存输出内容的复本,例如html页面、图片文件等,然后,当下一个请求来到时,如果是相同的URL,缓存直接使用复本相应请求访问,而不是向源服务器再次发送请求。
web缓存的具体实现是由浏览器来实现的。浏览器在计算机上开辟一块磁盘空间用于存储已经看过的网站的副本。浏览器缓存根据非常简单的规则进行工作:在同一个会话过程中会检查一次并确定缓存的复本足够新。这个缓存对于用户单击后退或者单击刚访问过的连接特别有用,如果你浏览过程中访问到同一个图片,这些图片可以从浏览器缓存中调用并即时显现。
一、客户端缓存规则
前段页面缓存主要遵循HTTP协议和客户端的设置工作。
1、不会缓存的情况如下:
- 如果相应头信息告诉缓存器不要保留缓存,缓存器就不会缓存相应内容。
- 如果请求信息需要认证或者加密安全,相应内容也不会缓存。
- 如果在回应中不存在校验器(ETag或者Last-Modified头信息),缓存服务器会认为缺乏直接的更新度信息,内容会被认为不可缓存。
2、将会缓存的情况如下:
- 含有完整的过期时间和寿命控制头信息,并且内容扔在保鲜期内。
- 浏览器已经使用过缓存副本,并且在一个会话中已经检验过内容的新鲜度。
- 缓存代理服务器近期内已经使用过缓存副本,并且内容的最后更新时间在上次使用期之前。
- 够新的副本将直接从缓存中送出,而不会向源服务器发送请求。
- 如果缓存的副本已经太旧了,缓存服务器将向源服务器发出校验请求,用于确定是否可以继续使用当前拷贝继续服务。
二、HTTP协议中的缓存使用
在客户端,通过浏览器发出第一次请求,请求某一个URL时,根据HTTP协议的规定,浏览器会向服务器传送报头,服务器响应同时记录相关属性标记,服务器的返回状态会是200;客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送报头,服务器响应请求,并查询到标记文件有没有发生变动,服务器段返回304,浏览器收到此状态码后,直接从本地缓存中读取。
其中last-Modified、Expires和ETag是页面缓存表示:
1、Expires:告诉浏览器相关副本在多长时间内是新鲜的。过了这个时间,缓存器就会想服务器发送请求,检验文档是否被修改。该属性对设置静态图片文件可缓存特别有用。记住HTTP的日期时间必须是格林威治时间(GMT),而不是本地时间。
2、Cache-Control:HTTP1.1介绍了另外一组头信息属性。通过这个属性可以让网站发布者全面控制内容,并定位过期时间的限制。
- max-age=[秒]:缓存过期时间,单位是秒,从请求时间开始到过期时间之间的秒数;
- s-maxage=[秒]:类似于max-age属性,不同的是,他应用于共享(如代理服务器)缓存;
- public:标记认证内容也可以被缓存,一般来说,经过HTTP认证才能访问的内容,输出时自动不可以缓存的。
- no-cache:强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。
- on-store:强制缓存在任何情况下都不要保留任何副本。
- must-revalidate:如果服务器段明确指出资源的过期时间或者保鲜时间,并且声明了资源的修改时间或者ETag之类的表示,那么就有一个问题,在保鲜的时间内,如果用到了该资源,是不是要到服务器确认一下资源是否最新的。如果服务器声明了must-revalidate,则每次使用该资源都要确认该资源的新鲜性。
- proxy-pevalidate:支队缓存代理服务器起作用。
例如:cache-control:max-age=3600,must-revalidate
3、last-modified:文档的最后修改时间。客户端第一次访问,服务器段返回last-modified标记此文件在服务器段最后被修改的时间;第二次请求,根据HTTP协议的规定,浏览器会向服务器传送if-modified-since报头,询问该时间过后文件是否被修改过,如果服务器端没有变化,则自动返回HTTP 304状态,内容为空,客户端应用缓存资源,这样就节省了数据量。
4、ETag:服务器生成的唯一标识符ETag,每次副本的标签都会变化。客户端通过ETag询问服务器端资源是否改变。ETag和Last-Modified都能起到文档唯一性标示的作用。
三、通过php程序设置HTTP header信息
1、通过php程序设置header来控制缓存的生成和过期的策略
header('Cache-Control:max-age=86400,must-revalidate'); header('Last-Modified:'.gmdate('D,d M Y H:i:s').'GMT'); header('Expires:'.gmdate('D,d M Y H:i:s',time()+'86400').'GMT');
点击页面中的链接,利用浏览器的回退按钮返回,再次单击页面中的链接,无论如何后退和点击链接,网络请求URL这一条始终未灰色,表示浏览器并没有发起实际的网络请求,而直接用的浏览器缓存,除非缓存过期。
注意:只有出现三种情况浏览器才会更新缓存----缓存到期;缓存被清除;按F5或Ctrl+F5强制刷新。
2、通过php程序设置header,每次请求都从服务器获取数据
//告诉浏览器不使用缓存,HTTP1.1协议 header("Cache-control:no-cache,must-revalidate"); //告诉客户端浏览器不适用缓存,兼容HTTP1.0协议 header("Pragma:no-cache");
四、通过nginx配置设置浏览器缓存
nginx可以通过 expires 指令来设置浏览器的Header
- 语法: expires [time|epoch|max|off]
- 默认值: expires off
- 作用域: http, server, location
使用本指令可以控制HTTP应答中的“Expires”和“Cache-Control”的头标(起到控制页面缓存的作用)。
- 可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的 time 值来获得。
- epoch 指定“Expires”的值为 1 January, 1970, 00:00:01 GMT。
- max 指定“Expires”的值为 31 December 2037 23:59:59 GMT,“Cache-Control”的值为10年。
- -1 指定“Expires”的值为 服务器当前时间 -1s,即永远过期
例子如下:
//图片缓存三十天 location ~.*\.(jpg|png|jpeg)$ { expires 30d; } //js css缓存一小时 location ~.*\.(js|css)?$ { expires 1h; }