HTTP 协议中,缓存更多关心的文档资源的再利用。其目的是减少数据传输,加快相应速度等等。而对于缓存采用的是什么方案,也就是存在内存中还是硬盘中之类的问题,就属于另外的内容了。

  假设,我身在广东,但是我访问的服务器在北京,在服务器其他条件一致的时候,我访问北京的服务器所需要的速度,肯定没有访问广东的服务器快。此时如果先访问靠近我的服务器,先看看我需要的资源有没有相应的副本,有就直接返回;没有就到源服务器中请求。这样响应速度肯定会快很多,而且也减轻了源服务器的压力。当然这里还有‘缓存命中率’和‘字节命中率’之类的概念,关于这些概念可以通过阅读《HTTP权威指南》这本书,当然这本被誉为‘HTTP开发者的圣经’的书非常的厚,当我第一次拿到这本书的时候,其实内心也是崩溃的。

  下面的内容其实更像是读书笔记,外加一下个人理解、总结。

  缓存处理的步骤:

  1.接收——从网络中接收相应的请求报文

  2.解析——对请求报文进行解析,读取其请求的URL和其他首部

  3.查询——查询请求的资源本地是否有相应的‘新鲜’副本可用,如果用,就直接使用,如果没有,就去源服务器请求一份,并将其保存至本地。

  4.新鲜度检测——检查缓存的副本是否足够‘新鲜’,如果不是,就去源服务器确认是否有任何的更新

  5.创建响应——使用缓存的副本或者是从源服务器得到的新内容,加上相应的首部,构建一条响应报文

  7.发送——将响应报文发回给客户端

  8.日志——可选地创建一条日志来记录这次事务

  这个处理步骤针对的是缓存服务器,当然这个缓存服务器可以是服务商架设的,也可以是客户端浏览器自带的。现代的浏览器一般都会自带缓存,可以在网景系的浏览器可以在 URL 栏中输入:about:cache ,来查看本地缓存的使用情况。这里引入一个公有缓存私有缓存的概念,可以通过首部:Cache-Control 的值来规定:

  Cache-Control: public (可以向任意方提供响应的缓存,也就是公有缓存)

  Cache-Control: private (仅向特定用户返回响应,也就是私有缓存)

  但这里,我个人有一个问题:是不是私有缓存就存在浏览器缓存中,而公有缓存就存在缓存服务器中呢?很明显这个要求貌似是合理的,但是具体是否就是这样,《HTTP权威指南》中并没有明说,而在另一本书《图解HTTP》中,提及了缓存服务器可以缓存私有缓存,但只能为特定的用户提供。

  而浏览器又会缓存公有缓存,所以浏览器的缓存更像是一个私有的缓存服务器,只不过这个缓存服务器是私有的,所以是公有还是私有缓存意义就不大了。

  所以这里的公有和私有只针对响应报文本身吧。

  接下来是就按照处理步骤走一遍了,这里我们先假设缓存服务器中没有缓存任何的内容先,此时我的客户端向缓存服务器发送一个请求报文,因为此时缓存服务器什么都没有,所以肯定会去源服务器中请求资源,此时源服务器构建了一个响应报文,发给了缓存服务器,缓存服务器读取了相应的首部,然后进行缓存策略的调整。

  在这个过程中又引入了几个首部:

  Date:表示报文创建的时间,当然使用的时间是服务器的时间,而且一般是 GMT 时间,当然格式有很多种,在 HTTP/1.1 中使用 RFC1123 中规定的格式。这是一个通用首部,服务器和客户端都可以使用,但服务器一般要给出这个首部,因为这个首部将用来计算缓存的新鲜度。对客户端而言,这个首部是可选的,当然有会更好一些。

  下面是我打开某个网站时,其中一个响应报文的首部:

  当然,中国在东八区,所以换算成中国时间应该是,3月21日 13:15:22 。但是,当我打开这个网页的时候,已经是6月21日 15:40 左右了,也就是说这个报文是三个月前创建的,很明显,这个报文被缓存了,而且在我请求的时候,缓存服务器还判断其没有过期,还是‘新鲜的’。

  注意:一般要求代理服务器不能改写 Date 首部。


  Age:表示源服务器在多久之前创建了响应,单位为秒,例如上面例子中报文中:

  8043650/60/60/24/30 = 3.103....

  但是,如果创建这个响应报文的是缓存服务器,Age 指的是缓存后的响应报文再次认证,到认证完成的时间。


  Last-Modified:该首部试图提供这个实体最后一次被修改的相关信息。对于静态资源,例如文件、图片等,表示的是最后修改的时间;对于那些动态创建的资源,如使用脚本创建的资源,这个值可能就是创建响应的时间。

  注意:这个时间不能是未来时间,如果它比 Date 首部还要迟,HTTP 服务器就会将该时间重置。

  因为我请求的是


  Cache-Control: max-age

  Cache-Control 这个首部主要是实现缓存控制的,它有许多的属性,我们在前面已经学习过表示私有缓存和公有缓存的属性了。这里的 max-age 属性表示资源过期的相对时间——从第一次生成文档到文档不再新鲜、无法使用为止,最大的合法生存时间,单位是秒。

  例如上面示例中的相应报文中:

  315360000/60/60/24/365 = 10 ,也就是说该资源的最大有效时间是 10 年。


  Cache-Control: s-maxage

  其行为和 max-age 类似,但仅适用于公有缓存。


  Expires:指定一个绝对过期时间,如果过了过期时间,说明文档不再‘新鲜’。其实其和 max-age 做的事是一样的,只不过 max-age 是 HTTP/1.1 中的,而 Expires 是 1.0+ 版本中的。一般而言更趋向使用max-age,因为服务器之间的时间很大可能会出现偏差。假如你希望一个文档明天就过期,而缓存服务器的时间比源服务器晚一天,那么到期时间就会变成后天,也就是说 Expires 参照的是缓存服务器的时间,而max-age 则表示在从服务器将文档传来之时起,可以认为其是新鲜的秒数,所以即使缓存服务器的时间不准也没有关系

  上面示例中的相应报文中:

  可能其和 max-age 的过期时间不同,当两者同时出现的时候,如果缓存服务器是 HTTP/1.1 版本的,则 max-age 的优先级更高,同时会忽略 Expires,而 1.0+ 就会执行 Expires 而无视 max-age ,一般源服务器为了兼容性,都会同时发生这两个首部。


  知道了以上首部之后,就可以知道了解到下面的内容了:在3个月前的某一天,缓存服务器还是空的,可能那个时候它还是新部署的,又或者是原来的缓存被删除了之类的。此时有一个客户端请求这个资源,缓存服务器一看,自己没有这个资源,就去源服务器请求,源服务器生成了这个响应,当时的时间是 Date 首部显示的时间。然后通过 Last-Modified 说明这个文档的修改相关信息,然后用 max-age、x-maxage、Expires 控制有效期。

  缓存服务器收到报文后,按照首部的要求缓存下来,下次有请求相同资源的,在有效期内就可以直接用缓存的资源响应了。

  那么客户端,也就是我们的浏览器是怎么样利用缓存的呢?

  首先,我们的浏览器并不知道其是和缓存服务器通信,还是和源服务器通信。最多就是通过 Via 首部得知请求经过了几层代理。而且我们浏览器也不在意是否和源服务器通信, 只有获得相应报文就行了。也就是说,当我们打开一个新的网页,或者强制刷新一个网页,其得到的都是 200 ok 响应。

  以上就是我用火狐浏览器强制刷新我的博客首页的所有请求,可以看到所有都是 200 的状态码。也就是说第一次请求的时候,都是从服务器中获取的资源。这个服务器可能是缓存服务器。

  当我第二次刷新这个页面的时候:

  却发现部分 304 的响应状态码。304 Not Modified 代表资源没改变,可以继续使用副本。

  我们看看第一次请求的时候,背景图片的响应报文是什么吧:

  其中 Last-Modified 已经解释过了,Etag 首部代表的是文件的描述符,这个东西有点类似文件的 MD5 值,每当文件改变后,其 MD5 值也会改变。所以这个标识符是用来说明文件是否有改变,当然其是否就是文件的 MD5 值我并没有研究过。总之用来表明文件是否有修改过,当然还有弱标识符的用法,在值前面加上 w/ 表示弱标识符,更多详细信息,请参考书本。

  那么,当我们普通刷新页面的时候,其请求报文是这样的:

  我们可以发现这里有两个首部:If-Modified-Since,If-None-Match,这两个是条件请求首部,表示如果其里面的条件为真,就执行相应的方法。其表示,如果当前请求的资源在指定的日期后发生了改变,条件就为真,就执行相应的 GET 之类的方法。

  仔细观察,可以发现 If-Modified-Since 和 Last-Modified 的日期就一样的。这里的意思是:在上次的响应之后,文件最后修改时间发生了变化,即文件发生了改变,就去源服务器请求新的资源。

  If-None-Match 则表示标识符和上次不符合的话,条件就为真,就请求新的资源。

  当服务器发送一个实体标签的时候,HTTP/1.1 客户端就必须使用实体验证,如果只发送 Last-Modified ,就可以使用 If-Modified-Since 验证。两者同时发送的时候,就使用两个验证,当两个验证成功(也就是两种方法判断,文件都没有修改),服务器才回送 304 响应。

  这就是新鲜度验证了,当然这里的例子说明的是浏览器缓存和服务器之间的验证,至于缓存服务器和源服务器的验证,我们是看不见的,不过原理也是差不多的。

  验证成功后返回 304 ,通常只有一个首部,比重发完整的资源节省许多;验证失败就返回 200 ,并将新资源发来,附带新的过期时间。


控制缓存的首部

  其实就是 Cache-Control 的各种属性:

1.Cache-Control: no-store

  服务器:当服务器发送此首部时,意味着该响应报文禁止缓存,缓存服务器会向客户端转发一条 no-store ,然后删除对象。

  客户端:当客户端发送此首部时,要求不要缓存请求报文。或者删除已缓存的资源。(当然缓存服务器是否接受该指令要看其配置如何)

  该指令暗示请求或响应报文中含有敏感或机密信息,缓存服务器不能在本地储存请求或响应的任一部分。

2.Cache-Control: no-cache

  服务器:当服务器发生此首部时,要求缓存服务器可以缓存此报文,但是在未经新鲜度确认之前,不能提供此缓存。如果指定了参数,例如:no-cache=Location,则表示客户端在接收到这个被指定的参数值的首部字段,例如:Location: www.xxx.com 时,就不能进行缓存,其他没有的就可以进行缓存,只能在响应报文中指定这个参数。

  客户端:当客户端发送此首部时,表示除非资源进行了再验证,否则这个客户端将不会接受已缓存的资源。这个再验证应该是收到该首部后立即进行的,其目的是为了防止返回过期的资源。

Pragma: no-cache

  是为了兼容 1.0+ 版本的首部,意思一样,有时为了兼容性会同时发生这两个首部。

3.Cache-Control: max-age

  服务器:控制缓存的最大有效期

  客户端:不接受已经缓存了多少秒的资源,如:max-age=600 表示不接受缓存超过1小时的资源。

4.Cache-Control: max-stale

  客户端:当没有值时,缓存服务器可以提供任意过期的资源,如果有了指定的值,例如:max-stale=600 ,表示可以接受已经过期1小时的资源。

5.Cache-Control: min-fresh

  客户端:必要要有指定值,表示如果在未来的多少时间内,资源仍然是新鲜的,则可以提供。例如:min-fresh=600,表示在未来的1小时之内依然没有过期的话,则提供给客户端。

6.Cache-Control: must-revalidate

  服务器:在没有跟原始服务器再验证的时候,不能提供此缓存的资源。缓存服务器依然可以对资源进行缓存,但是如果在进行验证的时候,源服务器不可用,则缓存服务器会返回一条 504 Gateway Timeout 错误(个人感觉和 no-cache 在功能上差别不大。)

7.Cache-Control: only-if-cached

  客户端:只有当缓存服务中有副本存在时,客户端才会获取一份副本。


关于 HTTP 中的缓存就先总结到这里,以后有什么错误的或者需要补充的再继续。

  

HTTP协议-缓存的更多相关文章

  1. Web缓存(一) - HTTP协议缓存

    为什么要使用 Web 缓存 Web缓存一般分为浏览器缓存.代理服务器缓存以及网关缓存,本文主要讲的是 浏览器缓存,其它两种缓存大家自行去了解下. Web 缓存游走于服务器和客户端之间.这个服务器可能是 ...

  2. 06 HTTP协议缓存控制

    一:HTTP协议缓存控制 第1次请求时 200 ok 第2次请求时 304 Not Modified 未修改状态 解释: 在网络上,有一些缓存服务器,另, 浏览器自身也有缓存功能. 当我们第一次某图片 ...

  3. 浏览器 HTTP 协议缓存机制详解

    最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag, ...

  4. HTTP协议缓存机制的应用

    缓存的目 的是减少相应延迟 和 减少网络带宽消耗, 比如 css. js.图片这类静态资源应该进行缓存.实际项目 一般使用反向代理服务器(如 nginx. apache 等) 进行缓存. 关键字:ca ...

  5. HTTP协议缓存策略深入详解之ETAG妙用

    Etag是什么: Etag 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等.具体内部含义是使服务器控制的,就像Cookie那样. HTTP协议规格说明定义 ...

  6. nginx平台初识(二) 浏览器 HTTP 协议缓存机制详解

    1.缓存的分类 缓存分为服务端侧(server side,比如 Nginx.Apache)和客户端侧(client side,比如 web browser). 服务端缓存又分为 代理服务器缓存 和 反 ...

  7. AJAX-URL-HTTP协议-缓存-DOM操作-HTML元素事件

    1.URL 1.URL的作用 用于来表示任意一个资源的位置(互联网上). 协议+主机名+文件目录结构+文件名称 2.详解 格式: <scheme>://<user>:<p ...

  8. 浏览器 HTTP 协议缓存机制详解--网络缓存决策机制流程图

    1.缓存的分类 2.浏览器缓存机制详解 2.1 HTML Meta标签控制缓存 2.2 HTTP头信息控制缓存 2.2.1 浏览器请求流程 2.2.2 几个重要概念解释 3.用户行为与缓存 4.Ref ...

  9. HTTP 协议缓存

    http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加 ...

随机推荐

  1. map文件的使用

    map文件相信大家并不陌生,大家都知道是用来调试的,但是具体怎么用你又清不清楚呢? 其实也很简单 1.拿JQ为例,我们需要备有jquery.js.jquery.min.js.jquery.min.ma ...

  2. bzoj千题计划199:bzoj1055: [HAOI2008]玩具取名

    http://www.lydsy.com/JudgeOnline/problem.php?id=1055 区间DP dp[i][j][k] 表示区间[i,j]能否合成k #include<cst ...

  3. ActiveMQ Transport Connectors

    一,介绍 ActiveMQ的Transport Connectors 是什么? ActiveMQ是一个消息服务器.作为消息服务器,就会有生产者和消费者来使用它.生产者将消息发送给ActiveMQ,消费 ...

  4. 20155237 2016-2017-2 《Java程序设计》第7周学习总结

    20155237 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 认识Lambda语法 Lambda 教材的引入循序渐近.深入浅出 Lambda去重复,回忆D ...

  5. GORM 中文文档

    由于篇幅问题,本文只是快速开始部分,下面是完整地址. 中文文档地址:http://gorm.book.jasperxu.com/ 中文文档项目地址:https://github.com/jasperx ...

  6. <td>内容超出自动换行

    td 内容自动换行 table表格td设置宽度后文字太多自动换行 设置table 的 style="table-layout:fixed;" 然后设置td的 style=" ...

  7. 什么是BS,BS和CS的区别有哪些

    BS和CS的区别以及优缺点 C/S又称Client/Server或客户/服务器模式.服务器通常采用高性能的PC.工作站或小型机,并采用大型数据库系统,如Oracle.Sybase.Informix或 ...

  8. Dream------Hbase--0.94版本和0.98/1.X版本api变动

    Dream------Hbase--0.94版本和0.98/1.X版本api变动 网上好多说getQualifier.getValue.getRow被..Array代替了,其实并不是的. 1. Int ...

  9. Linux环境下段错误的产生原因及调试方法小结【转】

    转自:http://www.cnblogs.com/panfeng412/archive/2011/11/06/2237857.html 最近在Linux环境下做C语言项目,由于是在一个原有项目基础之 ...

  10. Linux驱动技术(五) _设备阻塞/非阻塞读写【转】

    转自:http://www.cnblogs.com/xiaojiang1025/p/6377925.html 等待队列是内核中实现进程调度的一个十分重要的数据结构,其任务是维护一个链表,链表中每一个节 ...