从需求看HTTP缓存

前端经常会被问HTTP缓存,那么HTTP缓存的发展了解多少呢?为什么会出现各种不同的缓存字段?本篇文章会从缓存的类型开始,逐一说明缓存相关的HTTP字段,相信读完会对以上的问题有所了解。注意,以下讲解只针对HTTP缓存的情况。

缓存分强缓存协商缓存两种,简单来讲的话,强缓存期间请求不会到达服务器,即在缓存有效期内命中缓存,浏览器会使用本地缓存;协商缓存是在没有命中缓存或强缓存失效的情况下,与服务器进行协商来决定返回的请求资源。大概的流程如下:

简略的请求流程

看完上图,从整体上我们了解了HTTP请求的流程,那么这里又引出一些问题,如何知道强缓存的存在?依赖什么条件来确定本地是否有效呢?要解答这些问题,就得知道两个HTTP响应头字段ExpiresCache-Control
HTTP/1.0规范中,响应头字段有一个Expires字段,用于表示当前资源过期的时间。该字段描述的是一个绝对时间,由服务器返回,客户端本地只要超过这个时间则缓存失效。
示例Expires: Sun, 24 May 2020 07:41:19 GMT
Expires是最初的缓存控制字段,为它开始web应用减少了很多不必要的带宽浪费,可以指定一些不常更新的文件形成缓存。但开发者们很快发现了新的问题,Expires依赖客户端的时间进行判断,客户端修改了时间会影响缓存的有效性,这在某些情况下会比较致命,比如一个重要文件,理应在今天过期,但由于客户端时间修改成了去年,造成了缓存没有刷新,这就会很尴尬。为了解决这个问题,在HTTP/1.1中加入了Cache-Control字段来控制缓存,以满足更多的需求,配置如下。需要注意的是,该字段优先级高于Expires

  • public 可以被所有用户缓存,这里包括浏览器、代理服务器、CDN等。
  • private 只能被浏览器缓存,不允许被其它如代理服务器缓存。
  • no-store 不缓存
  • no-cache 先缓存本地,但命中缓存后必须与服务器验证资源新鲜度才能使用。这里注意,不要被名字误导成不缓存了。
  • max-age 用相对时间来表示缓存有效期,表示缓存将在XX秒后失效。示例Cache-Control: max-age=315360000
    Cache-Control设置

如果在缓存有效期内命中缓存,则使用强缓存,但是,如果命中缓存时缓存失效了怎么办?这个时候就要进入协商缓存流程了。进入协商缓存的条件不单是缓存失效,还包含以下三种情况:

  • 第一次请求服务器,返回的响应头中没有Cache-ControlExpires
  • Cache-Control:max-ageExpires导致的缓存失效
  • Cache-Control: no-cache

当存在以上三种情况时,第二次请求服务器就会进入协商缓存流程。协商缓存过程也涉及了HTTP状态码的改变,当请求发现服务器存在缓存或且缓存没有更新时,更新缓存时间并返回304 Not Modified;如果缓存失效,则服务器会把最新资源的完整版返回给浏览器,状态码为200 OK。看到这里大概就已经明白了协商缓存的过程,但细想一下还有一些没有说清楚的地方,服务器是如何校验缓存的新鲜度的呢?

Last-Modified/If-Modified-Since

当浏览器首次请求服务器资源时,服务器会将请求资源的最新修改时间Last-Modified: Tue, 07 Apr 2020 06:24:10 GMT通过响应头部返回给浏览器,浏览器在下次发起同一资源请求时会带上该信息,通过在请求头部设置If-Modified-Since: Tue, 07 Apr 2020 06:24:10 GMT,服务器会比对Last-Modified/If-Modified-Since如果服务器的资源有更新,则将最新的资源返回给浏览器,并更新响应头中的Last-Modified值,此时响应状态码为200 OK;如果服务器资源没有更新(两者时间一致),浏览器直接使用缓存即可,此时响应状态码为304 Not Modified

ETag/If-None-Match/If-Match

理论上通过比对资源的最新更新时间即可判断缓存是否有效,但实际操作中还是会遇到问题,比如资源文件在一秒内多次修改、资源经过编辑但没有发生实质内容修改的情况,这些问题表明以Last-Modified来判断还不够精确,我们需要引入ETag字段。大体流程上ETagLast-Modified的校验差不多,区别在于ETag不使用文件修改时间,而是使用文件内容摘要算出来的hash值进行判断,只要资源实质发生修改就会刷新hash值。服务器通过响应头中的ETag告知浏览器文件缓存信息,那么浏览器是如何把ETag的信息发送给服务器的呢?有以下两种形式:

  • If-None-Match: ETag value:通知服务器,如果没有匹配上,则需要重新发送资源;如果匹配上则直接返回304 Not Modified。一般浏览器使用该字段来回传ETag值。
  • If-Match: ETag value:通知服务器,如果没有匹配上ETag,或当前ETag: *但没有资源实体,则返回412 Precondition Failed;如果匹配上了,则服务器不做任何处理。

采用分布式服务器(如CDN)时,需要保证各服务器上的ETag算法一致,才不会出现A服务器与B服务器同一文件不同ETag值的出现。

Pragma

在整理资料的时候还发现了这个字段,该字段是HTTP/1.0的遗留之物,按辈分讲与Expires平齐。该字段用来定义是否需要缓存,可选值只有Pragma: no-cache,这个就可以按照字面意义理解成不进行缓存,即每次都会请求服务器的资源。优先级来讲Pragma > Cache-Control > Expires,当然,现代规范还是推荐使用Cache-Control的。

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