HTTP缓存

缓存是解决性能问题的重要手段,使用缓存的好处很多,除了能让浏览器更快地加载网络资源之外,还会带来其他好处,比如节省网络流量和带宽,以及减少服务端的负担。

本文主要介绍HTTP缓存。

HTTP 缓存可以分为强制缓存和协商缓存。

强缓存

强缓存就是浏览器发起http请求,先查找是否有缓存,如果有且有效期内,则直接读取缓存。

缓存规则:

当浏览器向服务器发送请求的时候,服务器会将缓存规则放入响应头中返回给浏览器,控制强制缓存的字段分别是ExpiresCache-ControlCache-Conctrol的优先级比Expires高。

Expires

Expires是HTTP/1.0控制缓存的字段,值为服务器响应结果缓存的到期时间,即再次发送请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。

现在浏览器的默认使用的是HTTP/1.1,由Cache-Control替代Expires,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,而Expires的值是UTC(绝对)时间,如果客户端与服务端的时间由于某些原因(时区不同;客户端和服务端有一方的时间不准确)发生误差,或者客户端修改了本地时间,那么强制缓存直接失效。

Cache-Control

Cache-Control 取值为:

  1. public:所有内容都将被缓存(客户端和代理服务器都可缓存)
  2. private:所有内容只有客户端可以缓存,Cache-Control的默认取值
  3. no-cache:客户端缓存内容,但是否使用缓存则需要经过协商缓存来验证决定
  4. no-store:所有内容都不会被缓存.。即每次请求都向服务器拿资源,服务器不会校验资源是否过期或有变化,而是直接返回资源
  5. max-age=xxx:缓存内容将在xxx秒后失效
  6. must-revalidate:本地资源过期前可以使用本地资源,本地资源一旦过期必须去源服务器进行有效性校验

当从缓存中读取资源时,根据缓存规则会有以下三种情况:

  1. 存在缓存结果和缓存标识,且缓存有效,则直接读取缓存资源,状态码为200(强缓存)
  2. 不存在缓存资源和缓存标识,强缓存失败,发起http请求
  3. 存在缓存结果和缓存标识,但缓存失效,则使用协商缓存。然后发起http请求,请求头中携带资源的缓存标识(Etag)对应字段:If-None-Match 和最后更新时间(Last-Modified)对应字段:If-Modified-Since,服务器根据这两个字段去判断:
    • 如果资源更新,则返回最新资源,状态码为200
    • 如果资源无更新,可继续使用缓存文件,状态码为304,浏览器收到响应后再去缓存中读取资源

浏览器的缓存存放在位置

内存(memory)和硬盘(disk)。浏览器读取缓存的顺序是memory cachedisk cache

内存缓存(memory cache)

内存缓存是将资源缓存在当前进程的内存中。

特点:

  1. 读取快:内存缓存会将编译解析后的文件(js、css、图片等)直接存入该进程的内存中,占据该进程的内存资源,在下次使用时快速读取
  2. 时效性:一旦该进程关闭,则该进程的内存则会清空
硬盘缓存(disk cache)

硬盘缓存是直接将资源写入硬盘中,读取资源需要对该资源存放的硬盘文件进行I/O操作,然后重新解析缓存的资源。比如关闭tab,再次打开,缓存在有效期内,从disk读取,重新解析。

特点:

读取复杂,速度比内存缓存慢。比如css文件。

协商缓存

协商缓存则需要先询问服务端资源是否发生改变,如果未改变再使用浏览器缓存。

控制协商缓存的触发方式:max-age为0或过期,或Cache-Control的值为no-cache,浏览器请求头携带该缓存的标识和最后更新时间向服务器发起请求,由服务器决定是否继续使用该缓存。

两种情况:

  1. 协商缓存生效,继续使用缓存,状态码304
  2. 协商缓存失败,返回最新资源,状态码200

协商缓存的标识也是在响应头中返回的,控制协商缓存的字段分别是:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。

Last-Modified(响应头) / If-Modified-Since(请求头)
  1. Last-Modified: 浏览器第一次请求资源时,服务器响应请求时,在请求头中返回该资源文件在服务器最后更新的时间。
  2. If-Modified-Since:客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器会根据该字段的值与该资源在服务器最后被修改时间做对比,若资源过期,则重新返回资源,状态码为200;否则返回304,并且不返回资源内容,可继续使用缓存文件。

这种方式虽然能判断缓存是否失效,但也存在两个问题:

  • 精度问题,Last-Modified 的时间精度为秒,如果在 1 秒内发生修改,那么缓存判断可能会失效;

  • 准度问题,考虑这样一种情况,如果一个文件被修改,然后又被还原,内容并没有发生变化,在这种情况下,浏览器的缓存还可以继续使用,但因为修改时间发生变化,也会重新返回重复的内容。

Etag(响应头) / If-None-Match(请求头)

为了解决精度问题和准度问题,HTTP 提供了另一种不依赖于修改时间,而依赖于文件哈希值的精确判断缓存的方式,那就是响应头部字段 ETag 和请求头部字段 If-None-Match。

具体工作流程如下:

浏览器第一次请求资源,服务端在返响应头中加入 Etag 字段,Etag 字段值为该资源的哈希值;

当浏览器再次跟服务端请求这个资源时,在请求头上加上 If-None-Match,值为之前响应头部字段 ETag 的值;

服务端再次收到请求,将请求头 If-None-Match 字段的值和响应资源的哈希值进行比对,如果两个值相同,则说明资源没有变化,返回 304 Not Modified,不返回资源内容;否则就正常返回资源内容,状态码为200。无论是否发生变化,都会将计算出的哈希值放入响应头部的 ETag 字段中。

这种缓存比较的方式也会存在一些问题,具体表现在以下两个方面。

  • 计算成本。生成哈希值相对于读取文件修改时间而言是一个开销比较大的操作,尤其是对于大文件而言。如果要精确计算则需读取完整的文件内容,如果从性能方面考虑,只读取文件部分内容,又容易判断出错。

  • 计算误差。HTTP 并没有规定哈希值的计算方法,所以不同服务端可能会采用不同的哈希值计算方式。这样带来的问题是,同一个资源,在两台服务端产生的 Etag 可能是不相同的,所以对于使用服务器集群来处理请求的网站来说,使用 Etag 的缓存命中率会有所降低。

注意:强制缓存的优先级高于协商缓存,在协商缓存中,Etag 优先级比 Last-Modified 高。

浏览器获取缓存资源的流程:

1. 首次访问:状态码200,黑色字体

首次访问

响应头字段

2. 600s内刷新,状态码200,灰色字体,从memory cache中读取资源

600s内刷新

3. 关闭tab,在缓存有效期内再次打开,状态码200,字体灰色,从disk cache读取资源

关闭tab,缓存有效期内再次访问

4. 缓存过期后刷新页面

缓存过期后刷新页面

http头

总结:

HTTP缓存分为强缓存和协商缓存。强缓存是直接从缓存中读取资源,状态码为200。协商缓存是强缓存失效(max-age过期)或Cache-Control值为no-cache,会发起http请求,请求头携带缓存资源的缓存标识Etag 和(或)最后更新时间Last-Modified,服务器接收到请求后做出判断,如果资源有更新,则状态码为304,表示继续使用缓存资源;反之,返回最新资源,状态码为200。

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