HTTP协议-缓存

  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 参照的是 Date 首部的时间(这要是为何代理服务器不能改写 Date 首部的原因之一),所以只有保证源服务器时间准确就可以了,而使用 Expires 则要保证两个服务器时间都准确。

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

  可能其和 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 中的缓存就先总结到这里,以后有什么错误的或者需要补充的再继续。

  

时间: 2024-08-27 20:13:44

HTTP协议-缓存的相关文章

06 HTTP协议缓存控制

一:HTTP协议缓存控制 第1次请求时 200 ok 第2次请求时 304 Not Modified 未修改状态 解释: 在网络上,有一些缓存服务器,另, 浏览器自身也有缓存功能. 当我们第一次某图片时,正常下载图片,返回值200 基于一个前提--图片不会经常改动, 服务器在返回200的同时,还返回该图片的”签名”-- Etag  ,(签名可以理解图片的”指纹”). 当浏览再次访问该图片时,去服务器校验”指纹”, 如果图片没有变化,直接使用缓存中的图片,这样减轻了服务器负担. 二:抓包观察分析

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

为什么要使用 Web 缓存 Web缓存一般分为浏览器缓存.代理服务器缓存以及网关缓存,本文主要讲的是 浏览器缓存,其它两种缓存大家自行去了解下. Web 缓存游走于服务器和客户端之间.这个服务器可能是源服务器(资源所驻留的服务器Add),数量可能是1个或多个:这个客户端也可能是1个或多个.Web 缓存就在服务器-客户端之间搞监控,监控请求,并且把请求输出的内容(例如html页面. 图片和文件)(统称为副本)另存一份:然后,如果下一个请求是相同的 URL,则直接请求保存的副本,而不是再次麻烦源服务

基于memcached协议缓存层流量管理工具:Mcrouter

随着这次门户功能改造的深入,对各个功能模块有了更加深刻的认识,昨天在编码的过程中看到工程中引用的memcache缓存层流量管理工具:Mcrouter,结合原来了解到的Nginx在这里对这款Facebook的新产品的功能做一个介绍: 在去年的[email protected]大会和USENIX的USENIX的NSDI(联网系统设计和实现座谈会)上我们就提过会将缓存换成我们自主开发的分布式软件系统,我们称之为mcrouter(发音"mick-router").Mcrouter是一个memc

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

1.缓存的分类 2.浏览器缓存机制详解 2.1 HTML Meta标签控制缓存 2.2 HTTP头信息控制缓存 2.2.1 浏览器请求流程 2.2.2 几个重要概念解释 3.用户行为与缓存 4.Refer: https://www.cnblogs.com/520yang/articles/4807408.html 最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里

HTTP 协议缓存

http 缓存分为客户端缓存和服务端缓存 1. 客户端缓存 客户端缓存指的是浏览器缓存, 浏览器缓存是最快的缓存, 因为它直接从本地获取(但有可能需要发送一个请求), 它的优势是可以减少网络流量, 加快请求速度 2. 服务器缓存 服务器缓存指的是反向代理服务器或 cdn 缓存, 他的作用是用于减轻实际的 web server 的压力. 缓存生效都是通过 header 来控制的 1. Expires 如果 repsonse 中带有 Expires=date, 则表示这个 response 可以由

http协议-缓存控制:no-cache/must-revalidate/no-store

原文:http://hyj1254.iteye.com/blog/1165387 客户端从服务器请求数据经历如下基本步骤:   1.如果请求命中本地缓存则从本地缓存中获取一个对应资源的"copy":   2.检查这个"copy"是否fresh,是则直接返回,否则继续向服务器转发请求.   3.服务器接收到请求,然后判断资源是否变更,是则返回新内容,否则返回304,未变更.   4.客户端更新本地缓存.   no-cache的作用是:强制客户端跳过步骤2,直接向服务器

http协议缓存小结

缓存可以使用expire方式,设置到期时间,缓存的时间等于expire设置的时间减去当前的时间 也可以使用no-cache的方式进行缓存,当设置了no-cache的方式时,以no-cache的为准,expire不起作用 no-cache下常见的有no-store,no-cache,max-age,must-revalidate no-store,不做缓存,每次返回200,拉取最新的资源 no-cache缓存一份,每次会读取最新的缓存内容 max-age配合must-revalidate使用,每次

HTTP协议缓存

缓存的概念 缓存这个东西真的是无处不在, 有浏览器端的缓存, 有服务器端的缓存,有代理服务器的缓存, 有ASP.NET页面缓存,对象缓存. 数据库也有缓存, 等等. http中具有缓存功能的是浏览器缓存,以及缓存代理服务器. http缓存的是指:当Web请求抵达缓存时, 如果本地有“已缓存的”副本,就可以从本地存储设备而不是从原始服务器中提取这个文档. 缓存的好处 缓存的好处是显而易见的, 好处有, 1. 减少了冗余的数据传输,节省了网费. 2. 减少了服务器的负担, 大大提高了网站的性能 3.

http协议之缓存

http协议缓存控制 第一次请求时200 ok 第二次请求304 not modified 为修改状态 解释: 在网络上有一些缓存服务器,另外浏览器自身也有缓存功能. 当我们第一次访问某个图片的时候,正常下载图片返回200 ok 基于一个前提-图片不会经常改动,服务器在返回200的时候,还返回该图片的"签名" -- etag (签名可以理解为图片的"指纹") 当浏览器再次访问该图片时,去服务器校验"指纹" 如果图片没有变化,直接使用缓存中的图片,