HTTP缓存技术详解


title: HTTP缓存技术详解
date: 2018-05-21 14:20:06
tags:

  • HTTP
  • 缓存
    categories: 深入http

通过网络获取内容既缓慢,成本又高:大的响应需要在客户端和服务器之间进行多次往返通信,这拖延了浏览器可以使用和处理内容的时间,同时也增加了访问者的数据成本。因此,缓存和重用以前获取的资源的能力成为优化性能很关键的一个方面。

与缓存相关的HTTP头部字段

http1.0时期的缓存方案

头部名称 说明
Pragma 控制缓存行为,如果设置为no-cache,表示禁用缓存。和http1.1中的Cache-Control头部功能相似
Expires 过期时间,用的是服务器的时间,如果客户端和服务器时间不一致,则会存在缓存时间误差。http1.1可以用Cache-Control来实现相似的功能。

如果使用了Pragma: 'no-cache'的话,再设置Expires或者Cache-Control,就没有用了,说明Pragma的权值比后两者高。

如果设置了Expires之后,客户端在需要请求数据的时候,首先会对比当前系统时间和这个Expires时间,如果没有过那个时间,则直接读取本地磁盘中的缓存数据,不发送请求。

http1.1的缓存方案

通用头部字段,即请求和响应都可以包含

头部名称 说明
Cache-Control 控制缓存行为
Pragma http1.0的字段,作用和Cache-Control大体相同

  • Cache-Control作为请求头部
指令 参数 说明
no-cache 强制向源服务器再次验证
no-store 不缓存请求或相应的任何内容
max-age=[秒] 必需 相应的最大Age值
max-stale=(=[秒]) 可省略 接收已过期的响应
min-fresh=[秒] 必需 期望在指定时间内的响应仍有效
no-transform 代理不可更改媒体类型
only-if-cached 从缓存获取资源
cache-extension - 新指令标记(token)

Cache-Control: no-cache

使用 no-cache 指令的目的是为了防止从缓存中返回过期的资源。 客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接 收缓存过的响应。于是,“中间”的缓存服务器必须把客户端请求转发 给源服务器。

Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓 存时间数值比指定时间的数值更小,那么服务端就直接返回304,客户端会使用自己本地缓存的资源。 另外,当指定 max-age 值为 0,那么服务器就会使用ETag和modefied-time验证,来决定返回304还是200。

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略。

  • Cache-Control作为响应头部
指令 参数 说明
public 可向任意方提供响应的缓存
private 可省略 仅向特定用户返回响应
no-cache 可省略 缓存前必需先确认其有效性
no-store 不缓存请求或相应的任何内容
no-transform 代理不可更改媒体类型
must-revalidate 可缓存但必须再向源服务器进行确认
proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=[秒] 必需 响应的最大Age值
s-maxage=[秒] 必需 公共缓存服务器响应的最大Age值
cache-extension - 新指令标记(token)

Cache-Control: public

当指定使用 public 指令时,则明确表明其他用户也可利用缓存。

Cache-Control: private

当指定 private 指令后,响应只以特定的用户作为对象,这与 public 指令的行为相反。 缓存服务器会对该特定用户提供资源缓存的服务,对于其他用户发送 过来的请求,代理服务器则不会返回缓存。

Cache-Control: no-cache

如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不能对 资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资 源有效性进行确认,且禁止其对响应资源进行缓存操作。

Cache-Control: no-cache=Location

由服务器返回的响应中,若报文首部字段 Cache-Control 中对 no-cache 字段名具体指定参数值,那么客户端在接收到这个被指定参数值的首 部字段对应的响应报文后,就不能使用缓存。换言之,无参数值的首 部字段可以使用缓存。只能在响应指令中指定该参数。

Cache-Control: no-store

当使用 no-store 指令时,暗示请求(和对应的响应)或响应中包含机密信息。

注:从字面意思上很容易把 no-cache 误解成为不缓存,但事实上 no-cache 代表不缓 存过期的资源,缓存会向源服务器进行有效期确认后处理资源,也许称为 do-notserve-from-cache-without-revalidation 更合适。no-store 才是真正地不进行缓存。

因此,该指令规定缓存不能在本地存储请求或响应的任一部分。

Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓 存时间数值比指定时间的数值更小,那么客户端就不会发起请求,而是直接使用自己本地缓存的资源。 另外,当指定 max-age 值为 0,那么客户端一定会发起一个请求给服务端,服务端会进行资源的校验,决定返回304还是200。

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略。

Cache-Control: s-maxage=604800(单位 :秒)

s-maxage 指令的功能和 max-age 指令的相同,它们的不同点是 smaxage 指令只适用于供多位用户使用的公共缓存服务器 ,如CDN缓存。也就是 说,对于向同一用户重复返回响应的服务器来说,这个指令没有任何 作用。

另外,当使用 s-maxage 指令后,则直接忽略对 Expires 首部字段及 max-age 指令的处理。

cache-control指令流程图

图片51.png

请求头部字段

头部名称 说明
If-Match 比较ETag是否一致,和响应的ETag字段相对应
If-None-Match 比较ETag是否不一致,和响应的ETag字段相对应
If-Modified-Since 比较资源最后更新时间是否一致,和响应的Last-Modified字段相对应
If-Unmodified-Since 比较资源最后更新时间是否不一致,和响应的Last-Modified字段相对应

响应头部字段

头部名称 说明
Etag 资源匹配信息

响应实体头部字段

头部名称 说明
Expires http1.0的缓存过期时间字段
Last-Modified 资源最后一次修改时间

缓存校验字段

ETag

首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串 形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

另外,当资源更新时,ETag 值也需要更新。生成 ETag 值时,并没有 统一的算法规则,而仅仅是由服务器来分配。

资源被缓存时,就会被分配唯一性标识。例如,当使用中文版的浏览 器访问 http://www.google.com/ 时,就会返回中文版对应的资源,而 使用英文版的浏览器访问时,则会返回英文版对应的资源。两者的 URI 是相同的,所以仅凭 URI 指定缓存的资源是相当困难的。若在下 载过程中出现连接中断、再连接的情况,都会依照 ETag 值来指定资 源。

强 ETag 值和弱 Tag 值

ETag 中有强 ETag 值和弱 ETag 值之分。

强 ETag 值,不论实体发生多么细微的变化都会改变其值。

ETag: "usagi-1234"

弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产 生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。

ETag: W/"usagi-1234"

If-Match

形如 If-xxx 这种样式的请求首部字段,都可称为条件请求。服务器接 收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。

首部字段 If-Match,属附带条件之一,它会告知服务器匹配资源所用 的实体标记(ETag)值。这时的服务器无法使用弱 ETag 值。(请参 照本章有关首部字段 ETag 的说明) 服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致 时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响 应。

可以理解为客户端校验当前本地缓存是否在服务器端可用。

还可以使用星号(*)指定 If-Match 的字段值。针对这种情况,服务 器将会忽略 ETag 的值,只要资源存在就处理请求。可以理解为客户端强制请求服务器当前的资源实体。

这个值默认是上一次该资源响应头部的ETag字段值。

If-None-Match

首部字段 If-None-Match 属于附带条件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的实体标记(ETag)值与 请求资源的 ETag 不一致时,它就告知服务器处理该请求。如果一致,就返回304,表示告知客户端使用自己本地的缓存。

在 GET 或 HEAD 方法中使用首部字段 If-None-Match 可获取最新的资 源。因此,这与使用首部字段 If-Modified-Since 时有些类似。

这个值默认是上一次该资源响应头部的ETag字段值。

Last-modified

Last-Modified: Wed, 23 May 2012 09:59:55 GMT

首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个 值就是 Request-URI 指定资源被修改的时间。

If-Modified-Since

If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT

首部字段 If-Modified-Since,属附带条件之一,它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。 而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源 都没有过更新,则返回状态码 304 Not Modified 的响应。

这个值默认是上一次该资源响应实体头部的Last-Modified字段值。

If-Unmodified-Since

If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT

首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相 反。它的作用的是告知服务器,指定的请求资源只有在字段值内指定 的日期时间之后,未发生更新的情况下,才能处理请求。如果在指定 日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应 返回。

可以理解为客户端校验当前本地缓存是否在服务器端可用。

这个值默认是上一次该资源响应实体头部的Last-Modified字段值。

缓存分类

强缓存

强缓存在客户端和服务器端都会存在。

客户端:客户端在请求资源前,会检查上一次该资源响应头的Cache-Control字段,如果该字段的值为max-age=time(大于0的秒数),如果该资源缓存的时间没有过这个时间值,则直接使用本地的缓存,而不像服务器发请求。

服务器端:服务器端在接收到一个请求后,如果该请求的头部Cache-Control字段的值为max-age=time(大于0的秒数),如果距离上一次返回资源的时间小于这个秒数,那么服务器不会读取新的资源,而是直接返回304,告知客户端使用自己本地上次缓存的资源即可。

:这两种情况,其实归根结底最后都是使用的客户端本地的资源,服务器没有返回资源实体。这样的好处是节省请求次数或者请求流量,但缺点是,如果在max-age时间内服务器资源有更新,客户端无法得到最新的服务器资源。此时可以通过Ctrl+F5强制刷新(其实就是设置一个Cache-Control:no-cache的请求头),获得最新的服务器资源。

协商缓存(对比缓存)

对比缓存值存在于服务器端。

在没有走强缓存逻辑的情况下,服务器端会进行Last-Modified和Etag的校验,如果校验发现资源未更新,则会返回304,否则会返回新的资源实体。

缓存流程图

图片61.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容