浏览器缓存详解:expires,cache-control,last-modified,etag详细说明
最近在对CDN进行优化,对浏览器缓存深入研究了一下,记录一下,方便后来者
画了一个草图:

每个状态的详细说明如下:
1、Last-Modified
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记(HttpReponse Header)此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头(HttpRequest Header),询问该时间之后文件是否有被修改过:
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
如果服务器端的资源没有变化,则自动返回HTTP304(NotChanged.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
注:如果If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求
2、Etag工作原理
HTTP协议规格说明定义ETag为“被请求变量的实体标记”(参见14.19)。简单点即服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式:
Etag:“5d8c72a5edda8d6a:3239″
客户端的查询更新格式是这样的:
If-None-Match:“5d8c72a5edda8d6a:3239″
如果ETag没改变,则返回状态304。
即:在客户端发出请求后,HttpReponse Header中包含Etag:“5d8c72a5edda8d6a:3239″
标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次需要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问得到的Etag:“5d8c72a5edda8d6a:3239″标识。
If-None-Match:“5d8c72a5edda8d6a:3239“
,这样,Client端等于Cache了两份,服务器端就会比对2者的etag。如果If-None-Match为False,不返回200,返回304(Not Modified) Response。
3、Expires
给出的日期/时间后,被响应认为是过时。如Expires:Thu, 02 Apr 2009 05:14:08 GMT
需和Last-Modified结合使用。用于控制请求文件的有效时间,当请求数据在有效期内时客户端浏览器从缓存请求数据而不是服务器端.当缓存中数据失效或过期,才决定从服务器更新数据。
4、Last-Modified和Expires
Last-Modified标识能够节省一点带宽,但是还是逃不掉发一个HTTP请求出去,而且要和Expires一起用。而Expires标识却使得浏览器干脆连HTTP请求都不用发,比如当用户F5或者点击Refresh按钮的时候就算对于有Expires的URI,一样也会发一个HTTP请求出去,所以,Last-Modified还是要用的,而且要和Expires一起用。
5、Etag和Expires
如果服务器端同时设置了Etag和Expires时,Etag原理同样,即与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.
6、Last-Modified和Etag
分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败
分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样)
Last-Modified和ETags请求的http报头一起使用,服务器首先产生Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改,来决定文件是否继续缓存
过程如下:
1.客户端请求一个页面(A)。
2.服务器返回页面A,并在给A加上一个Last-Modified/ETag。
3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
5.服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
注:
1、Last-Modified和Etag头都是由WebServer发出的HttpReponse Header,WebServer应该同时支持这两种头。
2、WebServer发送完Last-Modified/Etag头给客户端后,客户端会缓存这些头;
3、客户端再次发起相同页面的请求时,将分别发送与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;
4、通过上述值到服务器端检查,判断文件是否继续缓存;
7、关于 Cache-Control: max-age=秒 和 Expires
Expires = 时间,HTTP 1.0 版本,缓存的载止时间,允许客户端在这个时间之前不去检查(发请求)
max-age = 秒,HTTP 1.1版本,资源在本地缓存多少秒。
如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。
Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。
Expires =max-age + “每次下载时的当前的request时间”
所以一旦重新下载的页面后,expires就重新计算一次,但last-modified不会变化
每个状态的详细说明如下:
1、Last-Modified
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记(HttpReponse Header)此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified:Tue, 24 Feb 2009 08:01:04 GMT
客户端第二次请求此URL时,根据HTTP协议的规定,浏览器会向服务器传送If-Modified-Since报头(HttpRequest Header),询问该时间之后文件是否有被修改过:
If-Modified-Since:Tue, 24 Feb 2009 08:01:04 GMT
如果服务器端的资源没有变化,则自动返回HTTP304(NotChanged.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
注:如果If-Modified-Since的时间比服务器当前时间(当前的请求时间request_time)还晚,会认为是个非法请求
2、Etag工作原理
HTTP协议规格说明定义ETag为“被请求变量的实体标记”(参见14.19)。简单点即服务器响应时给请求URL标记,并在HTTP响应头中将其传送到客户端,类似服务器端返回的格式:
Etag:“5d8c72a5edda8d6a:3239″
客户端的查询更新格式是这样的:
If-None-Match:“5d8c72a5edda8d6a:3239″
如果ETag没改变,则返回状态304。
即:在客户端发出请求后,HttpReponse Header中包含Etag:“5d8c72a5edda8d6a:3239″
标识,等于告诉Client端,你拿到的这个的资源有表示ID:5d8c72a5edda8d6a:3239。当下次需要发Request索要同一个URI的时候,浏览器同时发出一个If-None-Match报头(Http RequestHeader)此时包头中信息包含上次访问得到的Etag:“5d8c72a5edda8d6a:3239″标识。
If-None-Match:“5d8c72a5edda8d6a:3239“
,这样,Client端等于Cache了两份,服务器端就会比对2者的etag。如果If-None-Match为False,不返回200,返回304(Not Modified) Response。
3、Expires
给出的日期/时间后,被响应认为是过时。如Expires:Thu, 02 Apr 2009 05:14:08 GMT
需和Last-Modified结合使用。用于控制请求文件的有效时间,当请求数据在有效期内时客户端浏览器从缓存请求数据而不是服务器端.当缓存中数据失效或过期,才决定从服务器更新数据。
4、Last-Modified和Expires
Last-Modified标识能够节省一点带宽,但是还是逃不掉发一个HTTP请求出去,而且要和Expires一起用。而Expires标识却使得浏览器干脆连HTTP请求都不用发,比如当用户F5或者点击Refresh按钮的时候就算对于有Expires的URI,一样也会发一个HTTP请求出去,所以,Last-Modified还是要用的,而且要和Expires一起用。
5、Etag和Expires
如果服务器端同时设置了Etag和Expires时,Etag原理同样,即与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.
6、Last-Modified和Etag
分布式系统里多台机器间文件的last-modified必须保持一致,以免负载均衡到不同机器导致比对失败
分布式系统尽量关闭掉Etag(每台机器生成的etag都会不一样)
Last-Modified和ETags请求的http报头一起使用,服务器首先产生Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改,来决定文件是否继续缓存
过程如下:
1.客户端请求一个页面(A)。
2.服务器返回页面A,并在给A加上一个Last-Modified/ETag。
3.客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。
4.客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。
5.服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。
注:
1、Last-Modified和Etag头都是由WebServer发出的HttpReponse Header,WebServer应该同时支持这两种头。
2、WebServer发送完Last-Modified/Etag头给客户端后,客户端会缓存这些头;
3、客户端再次发起相同页面的请求时,将分别发送与Last-Modified/Etag对应的HttpRequestHeader:If-Modified-Since和If-None-Match。我们可以看到这两个Header的值和WebServer发出的Last-Modified,Etag值完全一样;
4、通过上述值到服务器端检查,判断文件是否继续缓存;
7、关于 Cache-Control: max-age=秒 和 Expires
Expires = 时间,HTTP 1.0 版本,缓存的载止时间,允许客户端在这个时间之前不去检查(发请求)
max-age = 秒,HTTP 1.1版本,资源在本地缓存多少秒。
如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。
Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。
Expires =max-age + “每次下载时的当前的request时间”
所以一旦重新下载的页面后,expires就重新计算一次,但last-modified不会变化
原文地址:http://blog.csdn.net/eroswang/article/details/8302191
浏览器缓存详解:expires,cache-control,last-modified,etag详细说明的更多相关文章
- [转]浏览器缓存详解: expires, cache-control, last-modified, etag详细说明
最近在对CDN进行优化,对浏览器缓存深入研究了一下,记录一下,方便后来者 画了一个草图: 每个状态的详细说明如下: 1.Last-Modified 在浏览器第一次请求某一个URL时,服务器端的返回状态 ...
- 【转载】浏览器缓存详解:expires cache-control last-modified
https://www.cnblogs.com/caiyanhu/p/6931624.html 下面的内容展示了一个常见的 Response Headers,这些 Headers 要求客户端最多缓存 ...
- [面试专题]Web缓存详解
Web缓存详解 标签(空格分隔): 缓存 缓存之于性能优化 请求更快:通过将内容缓存在本地浏览器或距离最近的缓存服务器(如CDN),在不影响网站交互的前提下可以大大加快网站加载速度. 降低服务器压力: ...
- 【转】MySQL查询缓存详解
[转]MySQL查询缓存详解 转自:https://www.cnblogs.com/Alight/p/3981999.html 相关文章:http://www.zsythink.net/archive ...
- MySQL查询缓存详解(总结)
MySQL查询缓存详解(总结) 一.总结 一句话总结: mysql查询缓存还是可以用用试一试,但是更推荐分布式,比如redis/memcache之流,将数据库中查询的数据和查询语句以键值对的方式存进分 ...
- redis使用及配置之缓存详解
redis使用及配置之缓存详解 1.Redis的介绍 Redis是一个Key-Value存储系统.它支持存储的value类型有:string(字符串),list(链表), set(无序集合),zset ...
- 《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
1.简介 从这一篇开始介绍和分享Java+Selenium+POM的简单自动化测试框架设计.第一个设计点,就是支持跨浏览器测试. 宏哥自己认为的支持跨浏览器测试就是:同一个测试用例,支持用不同浏览器去 ...
- Hibernate缓存简介和对比、一级缓存、二级缓存详解
一.hibernate缓存简介 缓存的范围分为3类: 1.事务范围(单Session即一级缓存) 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象 ...
- Bitmap之内存缓存和磁盘缓存详解
原文首发于微信公众号:躬行之(jzman-blog) Android 中缓存的使用比较普遍,使用相应的缓存策略可以减少流量的消耗,也可以在一定程度上提高应用的性能,如加载网络图片的情况,不应该每次都从 ...
随机推荐
- appium + maven +jenkins 基本入门之二 新建maven 的java项目
1: 下载maven : 1.0 :设置maven的环境变量: 1.1: 设置maven本地仓库: 在下载好的maven文件夹找到 apache-maven-3.3.9/conf 文件夹下的setti ...
- Ninject之旅之四:Ninject模块
摘要 随着应用程序的增长,注册的服务列表跟着变长,管理这个列表将变得困难.Ninject模块是一个好的将我们的类型绑定分离到不同的绑定组的方式,它很容易地将分组组织到不同的文件中.将一个类变成一个Ni ...
- Notepad++根据语言类型自动选择对应编译器来编译代码
Notepad++的NppExec插件可以调用好多编译器来编译代码. 比如编译Java: NPP_SAVE javac "$(FULL_CURRENT_PATH)" java -c ...
- java自编时间工具类
package timeTools; import java.text.ParseException; import java.text.SimpleDateFormat; import java.u ...
- jQuery div内容间隔1秒动态向上滚动HTML、JS代码
demo1: <!DOCTYPE html> <html> <head> <title>div内容间隔1秒动态滚动</title> < ...
- Nginx系列一:信号与配置
一.Nginx与信号 Nginx支持平滑重启,相比于Apache,修改了配置文件后可以不需要先停止程序,再重新启动. 1.启动 nginx –c nginx.conf 其中,-c nginx.conf ...
- 大型网站一致性的基础理论---CAP/BASE
最近在看<大型网站系统与java中间件事件>这本书,收获颇多. 分布式事务希望在多机环境下可以像单机系统那样做到强一致,这需要付出比较大的代价.而在有些场景下,接受状态并不用时刻保持一致, ...
- BeanUtils.populate的作用
它是在org.apache.commons.beanutils.BeanUtils包中的一个方法. 方法的作用:将一些 key-value 的值(例如 hashmap)映射到 bean 中的属性. ...
- 简单的androidStudio 添加Jar包
感谢http://blog.csdn.net/ta893115871/article/details/46955791博主的文章, 1新建一个空项目 2在项目下添加一个新的moudle 3在该moud ...
- jQuery multiselect的使用
1,下载插件 https://github.com/ehynds/jquery-ui-multiselect-widget