HTTP缓存介绍

HTTP缓存

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。

使用缓存的优点:

  • 减少冗余的数据传输
  • 减少服务器负担
  • 加快客户端加载网页的速度

根据是否需要向服务器重新发起 HTTP 请求将缓存过程分为两个部分,分别是 强缓存协商缓存(弱缓存、对比缓存)

HTTP 缓存过程分析

浏览器 第一次 向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中,简单的过程如下图:

cache.jpg

由上图我们可以知道:

  • 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
  • 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

当浏览器 再次请求 该资源时,浏览器会先获取该资源缓存的 header 信息,根据其中的 ExpiresCache-Control 判断是否命中 强缓存,若命中则直接从浏览器缓存中获取资源,包括缓存的header信息,本次请求不会与服务器进行通信;如果没有命中强缓存,浏览器会发送请求到服务器,该请求会携带第一次请求返回的有关缓存的 header 字段信息(Last-Modified/IF-Modified-Since、Etag/IF-None-Match),由服务器根据请求中的相关 header 信息来对比结果是否命中 协商缓存,若命中,则服务器返回新的响应 header 信息更新缓存中的对应 header 信息,但是并不返回资源内容,它会告知浏览器从缓存获取资源;否则返回最新的资源内容

强缓存

当浏览器对某个资源的请求命中了强缓存时,返回的http状态为200,在chrome的开发者工具的network里面size会显示为from cache

强缓存是利用 http 的返回头中的 Expires 或者 Cache-Control 字段来控制的,用来表示资源在客户端缓存的有效期,Cache-Control 的优先级更高。

Expires

该字段是 http1.0 时的规范,它的值为一个 绝对时间 的GMT格式的时间字符串,比如 Expires:Mon,18 Oct 2022 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。

这种方式有一个明显的缺点,由于失效时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,缓存管理容易出现问题,比如随意修改下客户端时间,就能影响缓存命中的结果。因此,在 http1.1 的时候,提出了一个新的 header,就是 Cache-Control

Cache-control

Cache-Controlhttp1.1 时出现的header信息,默认取值为 private,常见取值有:

  • private:只有客户端可以缓存,不能作为共享缓存(即代理服务器不能缓存)(默认值)
  • public:表明响应可以被任何对象(发送请求的客户端、代理服务器等等)缓存
  • max-age=< secends >:设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)
  • no-cache:协商缓存验证,客户端缓存内容,但是能否使用缓存需要经过协商缓存来验证决定
  • no-store:不使用任何缓存, 强缓存和协商缓存都不会触发

注意:规则可以同时设置多个。

指定 no-cachemax-age=0, must-revalidate 表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。

最常使用的是利用该字段的 max-age 值来进行判断,它是一个相对时间。例如 Cache-Control:max-age=3600,代表着资源的有效期是3600秒。

如果在 Cache-Control 响应头设置了 max-age 或者 s-max-age 指令,那么 Expires 头会被忽略。

常见强缓存策略

  • Cache-Control: max-age=xxxx, immutable:
    客户端在xxx秒的有效期内,直接读取缓存, 状态码 200 ,即使用户做了刷新操作,也不向服务器发起http请求

协商缓存

协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。如果协商缓存命中,则返回 304 状态码并且会显示一个 Not Modified 的字符串,如果未命中,则会返回 200 状态码及最新的资源和缓存标识。

控制协商缓存的字段有下面2组:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中 Etag / If-None-Match 的优先级比 Last-Modified / If-Modified-Since 高。

Last-Modified / If-Modified-Since

Last-Modified

浏览器第一次请求一个资源的时候,服务器在响应头中会加上 Last-Modified,它标识该资源的最后修改时间,例如 Last-Modified: Thu,31 Dec 2037 23:59:59 GMT

If-Modified-Since

当浏览器再次请求该资源时,会在请求头中加上 If-Modified-Since,它的值为上次请求返回的 Last-Modified值。服务器收到该请求,则会根据If-Modified-Since的值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则返回304 Not Modified,代表资源无更新,可继续使用缓存文件,并且不会返回Last-Modified。

If-Modified-Since 只可以用在 GETHEAD 请求中,当与 If-None-Match 一同出现时,它(If-Modified-Since)会被忽略掉,除非服务器不支持 If-None-Match

Etag / If-None-Match

Etag

Etag 表示当前资源在服务器的唯一标识(生成规则由服务器决定)。

浏览器第一次请求时,服务器会在 响应头 中加上 Etag 字段。

If-None-Match

当浏览器再次请求该资源时,会在请求头中加上 If-None-Match,它的值为上次请求返回的 Etag值。
服务器收到该请求, 则会根据 If-None-Match的值和根据服务器资源重新生成新的 ETag 值进行比对,
若不同,说明资源被改动过,则返回新的资源内容,返回状态码200;
若相同,说明资源无新修改,则返回 304 Not Modified,告知浏览器可继续使用缓存文件,还是会返回新生成的 Etag

Etag 和 Last-Modified 对比

Etag 的出现主要解决了 Last-Modified 以下几个问题:

  • 某些文件可能仅仅改变了修改时间,内容并没有改变,这个时候我们并不希望客户端认为这个文件被修改了,而重新 GET
  • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since 能检查到的粒度是秒级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒)
  • 某些服务器不能精确的得到文件的最后修改时间

用户行为对缓存的影响

用户操作 Expires/Cache-Control Last-Modied/Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进回退 有效 有效
F5刷新 无效 有效
Ctrl+F5强制刷新 无效 无效

更新缓存

  • F5: 刷新网页时,会跳过强缓存,但是会检查协商缓存
  • Ctrl + F5: 强制刷新网页时,会直接从服务器加载,跳过强缓存和协商缓存
  • 版本号控制: 在资源请求的 URL 中增加一个版本号参数,比如:js/mian.js?ver=0.0.1。每次部署的时候变更一下版本号,当这个参数发生变化,强缓存都会失效并重新加载,这样就可以解决客户端升级时的缓存更新问题。

总结

强缓存优先于协商缓存进行,若强缓存 (ExpiresCache-Control) 生效则直接使用缓存,若不生效则进行协商缓存 (Last-Modified/If-Modified-SinceEtag/If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回304,继续使用缓存。

主要过程如下:

image.png

参考文章

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

推荐阅读更多精彩内容