HTTP之缓存是如何保持副本的新鲜的!
缓存保持副本的新鲜
========================摘自《HTTP权威指南》=================================
可能不是所有已缓存副本都与服务器上的文档一致。毕竟,这些文档会随着时间发生变化。报告可能每个月都会发生变化。在线报纸每天都会发生变化。财经数据可能每过几秒就会发生变化。如果缓存总是提供的老数据,就会变得毫无用处。已缓存的数据要与服务器的数据保持一致。
HTTP有一些简单的机制可以在不要求服务器记住有哪些缓存拥有文档副本的情况下,保持已缓存数据和服务器数据之间充分一致。HTTP将这些简单的机制称为文档过期(document expiration)和服务器再验证(server revalidation)。
1、 文档过期
通过特殊的HTTP Cache-Control首部和Expires首部,HTTP让原始服务器向每个文档附加一个“过期日期”。就像一夸脱牛奶上的过期日期一样,这些首部说明了在多长时间内将这些内容视为新鲜的。
在缓存文档过期之前,缓存可以以任意频率使用这些副本,而无需与服务器联系—当然,除非客户端请求中包含有阻止提供已缓存或未验证资源的首部。但一旦已缓存文档过期,缓存就必须与服务器进行核对,询问文档是否被修改过,如果被修改过,就要获取一份新鲜(带有新的过期日期)的副本。
2、 过期日期和使用期
服务器用HTTP/1.0+的Expires首部或HTTP/1.1的Cache-Control:max-age响应首部来指定过期日期,同时还会带有响应主体。Expires首部和Cache-Control首部所做的事本质上时一样的,但是由于Cache-Control首部使用的是相对时间而不是绝对日期,所以我们倾向于使用比较新的Cache-Control首部。绝对日期依赖于计算机时钟的正确设置。

3、 服务器再验证
仅仅是已缓存文档过期了并不意味着它和原始服务器上目前处于活跃状态的文档由实际的区别;这只是意味着到了要进行核对的时间了。这种情况被称为“服务器再验证”,说明缓存需要询问原始服务器文档是否发生了变化。
(1)、如果再验证显示内容发生了变化,缓存会获取一份新的副本,并将其存储在旧的文档位置上,然后将文档发送给客户端;
(2)、如果再验证显示内容没有发生变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新就行了。
缓存并不一定要为每条请求验证文档的有效性—只有在文档过期时它才需要与服务器进行再验证。这样不会提供陈旧的内容,还可以节省服务器的流量,并拥有更好的用户响应时间。
HTTP协议要求行为正确的缓存返回下列内容之一:
A、“足够新鲜的”已缓存副本;
B、与服务器进行再验证,确认其仍然新鲜的已缓存副本;
C、如果需要与之进行再验证的原始服务器出故障了,就返回一条错误报文;
D、附有警告信息说明内容可能不正确的已缓存副本;
4、用条件方法进行再验证
HTTP的条件方法可以高效的实现再验证。HTTP允许缓存向服务器发送一个“条件GET”,请求服务器只有在文档缓存中现有的副本不同时,才回送对象主体。通过这种方式,将新鲜度检查与对象获取结合成了单个条件GET。向GET请求报文中添加一些特殊的条件首部,就可以发起条件GET。只有条件为真时,Web服务器才返回对象。
HTTP定义了5个条件请求首部。对缓存再验证来说最有用的2个首部是If-Modified-Since和If-None-Match。所有的条件首部都以前缀“If-”开头。表7-3列出了在缓存再验证中使用的条件请求首部。

5、 If-Modified-Since:Date再验证
最常见的缓存再验证首部是If-Modified-Since。If-Modified-Since再验证请求通常被称为IMS请求。只有自某个日期之后资源发生了变化的时候,IMS才会指示服务器执行请求:
(1)、如果自指定日期后,文档被修改了,If-Modified-Since条件就为真,通常GET就会成功执行。携带新首部的新文档会被返回给缓存,新首部除了其他信息之外,还包含了一个新的过期日期。
(2)、如果自指定日期后,文档没有被修改过,条件就为假,会向客户端返回一个小的304 Not Modified响应报文,为了提高有效性,不会返回文档的主体。这些首部是放在响应中返回的,但只会返回那些需要在源端更新的首部。比如Content-Type首部通常不会被修改,所以通常不需要发送,一般会发送一个新的过期日期。
If-Modified-Since首部可以Last-Modified服务器响应首部配合工作。原始服务器会将最后的修改日期附加到所提供的文档上去。当缓存要对已缓存文档进行再验证时,就会包含一个If-Modified-Since首部,其中携带有最后修改已缓存副本的日期:
If-Modified-Since :<cached Last-Modified data>
如果在此期间内容被修改了,最后的修改日期就会有所不同,原始服务器就会回送新的文档。否则服务器会注意到缓存的最后修改日期与服务器文档当前的最后修改日期相符,会返回一个304 Not Modified响应。
6、 If-None-Match:实体标签再验证
有些情况下仅使用最后修改进行再验证是不够的。
(1)、有些文档可能会被周期性的重写(比如,从一个后台进程中写入),但实际包含的数据常常是一样的。尽管内容没有发生变化,但修改日期会发生变化。
(2)、有些文档可能被修改了,但所做的修改并不重要,不需要让世界范围内的缓存都重装数据(比如对拼写和注释的修改)。
(3)、有些服务器无法准确地判断其页面的最后修改日期。
(4)、有些服务器提供的文档会在亚秒间隙发生变化(比如,实时监视器),对这些服务器来说,以一秒为粒度的修改日期可能就不够用了。
为了解决这些问题HTTP允许用户对被称为实体标签(ETag)的“版本标识符”进行比较。实体标签是附加到文档是的任意标签(引用字符串)。他们可能包含了文档的序列号或版本名,或者是文档内容的校验和及其他指纹信息。
当发布者对文档进行修改时,可以修改文档的实体标签来说明这个新版本。这样,如果实体标签被修改了,缓存就可以用If-None-Match条件首部来GET文档的新副本了。
7、 强弱验证器
缓存可以用实体标签来判断,与服务器相比,已缓存的版本是不是最新的(与使用最近修改日期的方式很像)。从这个角度来看,实体标签和最近修改日期都是缓存验证器(cache validator)。
有时,服务器希望在对文档进行一些非实质性或不重要的修改时,不要使所有的已缓存副本都失效。HTTP/1.1支持“弱验证器”。如果只对内容进行了少量修改,就允许服务器声明那是“足够好”的等价体。
只要内容发生了变化,强验证器就会发生变化。弱验证器允许对一些内容进行修改,但内容的主要含义发生变化时,通常它还是会发生变化的。有些操作不能用弱验证器来实现(比如有条件地获取部分内容),所以,服务器会用前缀“W/”来标识弱验证器。
ETag:W/”v2.6”
If-None-Match:W/”v2.6”
不管相关的实体值以何种发生变化,强实体标签都要发生变化。而相关实体在语义上发生了比较重要的变化时,弱实体标签也要发生变化。
注意,原始服务器一定不能为两个不同的实体重用一个特定的强实体标签值,或者为两个语义不同的实体重用一个特定的弱实体标签值。不管过期时间是多少,缓存条目都可能会留存任意长的时间,因此,假设缓存不会再次通过它在过去某个时刻获得的验证器,对一个条目进行验证是不合适的。
8、 什么时候应该使用实体标签和最近修改日期
如果服务器回送了一个实体标签,HTTP/1.1客户端就必须使用实体标签验证器。如果服务器只回送了一个Last-Modified值,客户端就可以使用If-modified-since验证。如果实体标签和最后修改日期都提供了,客户端就应该使用这两种再验证方案,这样HTTP/1.0和HTTP/1.1缓存就可以正确的响应了。
除非HTTP/1.1原始服务器无法生成实体标签验证器,否则就应该发送一个出去,如果使用弱实体标签有优势的话,发送的可能就是个弱实体标签,而不是强实体标签。而且,最好同时发送一个最近修改值。
如果HTTP/1.1缓存或服务器收到的请求既带有If-modified-since,又带有实体标签条件首部,那么只有这两个条件都满足时,才能返回304 Not Modified响应。
HTTP之缓存是如何保持副本的新鲜的!的更多相关文章
- 前端学HTTP之缓存
前面的话 Web缓存是可以自动保存常见文档副本的HTTP设备.当Web请求抵达缓存时,如果本地有“已缓存的”副本,就可以从本地存储设备而不是原始服务器中提取这个文档.本文将详细介绍缓存的相关内容 功能 ...
- HTTP缓存
本文是<HTTP权威指南>读书笔记 Web缓存是可以自动保存常见文档副本的设备.当Web请求抵达缓存时,如果本地在“已缓存”的的副本,就可以从本地存储设备而不是原始服务器中提取这个文档.使 ...
- 浏览器缓存相关的Http头介绍:Expires,Cache-Control,Last-Modified,ETag
转自:http://www.path8.net/tn/archives/2745 缓存对于web开发有重要作用,尤其是大负荷web系统开发中. 缓存分很多种:服务器缓存,第三方缓存,浏览器缓存等.其中 ...
- HTTP权威协议笔记-7.缓存
7.1 冗余的数据传输 缓存的作用:当客户端每次访问服务器,服务器都会返回一份相同文件,一些相同的字节会不断的在网络内传输,这样冗余的数据传输会耗尽昂贵的带宽,降低传输速度,加重Web服务器的负载. ...
- HTTP中缓存相关
1.客户端如何区分缓存命中和未命中 两种情况下,返回的状态码都是200,客户端有一个方法可以判断,就是使用Date首部,将Date首部与当前时间进行比较,如果响应中时间日期值比较早,客户端可以认为这是 ...
- 关于缓存的tips——HTTP权威指南读书心得(十三)
上一章介绍了缓存新鲜度判断的基本原理,本章对于缓存新鲜度判断方法进行一些补充(更新间隔略长略长..). 关于缓存的TIPS 服务器可以通过http定义的几种header对可以缓存数据的存在时间进行控制 ...
- HTTP缓存机制[译文]
本文翻译自: https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching ,主要用于个人记录和共享,若有疏漏错误,请不吝指正,谢谢! 通过重用已 ...
- 分布式缓存-Memcached
分布式缓存出于如下考虑,首先是缓存本身的水平线性扩展问题,其次是缓存大 并发下的本身的性能问题,再次避免缓存的单点故障问题(多副本和副本一致性).分布式缓存的核心技术包括首先是内存本身的管理问题,包括 ...
- ATS缓存数据结构
ATS缓存数据结构 HttpTunnel类 数据传输驱动器(data transfer driver),包含一个生产者(producer)集合,每个生产者连接到一个或是多个消费者(comsumer). ...
随机推荐
- python语法01
在某.py文件中调用其他.py文件中的内容. 全局变量的使用. 线程的使用. if name == 'main': 的作用 新建两个python脚本文件 f1File.py ""& ...
- 开源工作流引擎 Workflow Core 的研究和使用教程
目录 开源工作流引擎 Workflow Core 的研究和使用教程 一,工作流对象和使用前说明 二,IStepBuilder 节点 三,工作流节点的逻辑和操作 容器操作 普通节点 事件 条件体和循环体 ...
- 面试官:来谈谈限流-RateLimiter源码分析
RateLimiter有两个实现类:SmoothBursty和SmoothWarmingUp,其都是令牌桶算法的变种实现,区别在于SmoothBursty加令牌的速度是恒定的,而SmoothWarmi ...
- pytest-Mark数据驱动
数据驱动 import pytest @pytest.mark.parametrize(("a", "b", "expected"), [ ...
- Struts2 常量配置
除了action的配置,struts还有其他的一些配置,比如编码方式. 这些配置用键值对来表示,键是固定的,是常量,所以也叫做常量配置. 常量配置有5种方式,Struts会按以下顺序依次搜索加载常量( ...
- spring boot的异常处理
原文:https://blog.csdn.net/tianyaleixiaowu/article/details/70145251 全局异常处理是个比较重要的功能,一般在项目里都会用到. 我大概把一次 ...
- X264-视频帧的存取
X264的编码器结构体x264_t中的子结构体字段frames包含了4个临时视频帧序列空间:current.next.unused和reference,分别保存当前编码帧.将编码帧序列.未处理原始视频 ...
- [日期工具分享][Shell]为特定命令依次传入顺序日期执行
[日期工具分享][Shell]为特定命令依次传入顺序日期执行 使用方式: <本脚本文件名(必要时需要全路径)> <要执行的命令所在的文件名> <开始日期> < ...
- Linux系统中ps -l命令显示的英文含义
UID:启动这些进程的用户.PID:进程的进程ID.PPID:父进程的进程号(如果该进程是由另一个进程启动的).C:进程生命周期中的CPU利用率.STIME:进程启动时的系统时间.TTY:进程启动时的 ...
- NLP中的预训练语言模型(四)—— 小型化bert(DistillBert, ALBERT, TINYBERT)
bert之类的预训练模型在NLP各项任务上取得的效果是显著的,但是因为bert的模型参数多,推断速度慢等原因,导致bert在工业界上的应用很难普及,针对预训练模型做模型压缩是促进其在工业界应用的关键, ...