推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 梅沙Fex > 浅谈 http 缓存

浅谈 http 缓存

梅沙Fex 2018-10-27

前言

浏览器缓存的方式有很多种,打开 Chrome 的控制台,点击 Application 模块,我们可以看到左侧的列表部分,它们其实就对应着浏览器的各种缓存机制。其中的 Frames 模块就是本文所要介绍的,也就是 http 缓存。当然,平时我们写代码时可能不用太操心这个东西,因为浏览器会自己搞定的,不过要知道有这么回事,万一哪天要用到呢。

什么是 http 缓存

比较官方的解释:http 缓存就是基于 http 协议的浏览器文件级缓存机制。
通俗来讲:就是当我们随便打开一个页面,浏览器就会自动的把页面缓存到本地,具体来说就是把该页面的某些资源(js、css和图片等)另存为到本地(也就是备份),下次当我们再访问该页面的时候,浏览器就可以从本地读取该页面的资源,缩短页面响应时间。

为什么要 http 缓存

  • 缩短页面响应时间(就是快啦),用户体验就蹭蹭蹭的上升

  • 减少对源服务器的请求,服务器的压力也因此降低

  • 爬虫能根据过期机制降低爬取的频率,提高爬虫效率

  • 减小网络带宽损耗,为用户和运营者剩下了一笔钱

需要了解的状态码

  • 200 OK 相当于第一次请求

  • 200 OK (from cache)  无请求,直接使用缓存

  • 304 Not Modified 有一次请求,发现资源未被更新,然后再使用缓存

需要了解的 Headers 信息

  • 缓存过期时间( Expires )

    形如:Expires: Thu, 29 Mar 2018 10:21:10 GMT

  • 另一个缓存过期时间( Cache-Control )

    形如:Cache-Control: max-age=2592000

  • 文件的最后修改时间( Last-Modified )

    形如:Last-Modified: Tue, 27 Feb 2018 09:33:08 GMT

  • 根据页面内容计算出来的实体标记( Etag )

    形如:ETag: W/"5a9525d4-63c6"Etag: "3760866945"

http 缓存的过程

第二步:当我们再次访问该 url 时,因为本地已经有了缓存(也就是备份),所以就暂且先不发送请求到服务器,而是到本地寻找缓存文件,看能不能用。这里的判断过程会按照如下顺序进行:

  • 先判断 `Expires` 和 `Cache-Control`:

a) 未过期 => 不发http请求,直接读取http缓存文件,打开控制台我们能看到返回的状态码是 200 OK(from cache)。(也称作强缓存)
b) 已过期 => 向服务器发送请求,并带上之前的 Last-Modified(放在 If-Modified-Since 字段里)和 Etag(放在 If-None-Match 字段里)信息
注意:如果两者同时存在,Cache-Control 的优先级高于 Expires,也就是忽略 Expires

  • 再判断 `Last-Modified` 和 `Etag`:

a) 若两者都没有变化,则服务器会返回 304 Not Modified 的状态码,以此来告知浏览器资源未被更新,你那边的缓存还能用,于是浏览器就会到本地缓存中去取对应的内容,期间浏览器和服务器有一次请求(又称作协商缓存或对比缓存)
b) 若两者有任何一个被改变,则服务器会受理此次请求,返回 200 OK,就像第一次请求那样
注意:如果两者同时存在,If-None-Match 的优先级高于 If-Modified-Since,也就是先判断 Etag

你可能会有的疑问

  • 为什么有了 Expires 还要 Cache-Control

因为响应报文中 Expires 所定义的过期时间是相对服务器而言的,要是服务器和客户端的时间不一样(比如用户自己修改了电脑的系统时间),缓存就会出现偏差。所以为了解决这个问题,Cache-Control 就出现了,可以理解为是对 Expires 的补充,使用的是相对时间(以秒为单位),是 Http1.1 中的标准,而 Expires 是 Http1.0 中的标准。
注意:若 ExpiresCache-Control 同时出现,则以 Cache-Control 为准。

  • 为什么有了 Last-Modified 还要 Etag

因为 HTTP1.1 中 Etag 的出现主要是为了解决 Last-Modified 解决不了的问题:比如我们在1秒内多次修改某个文件,由于 Last-Modified 的时间只能记录到秒级,所以它将不能正确表示文件的修改时间;又或者文件内容没有变化而 Last-Modified 改变了,我们也使用不了缓存。
注意:若两者同时存在,服务器会优先对比 ETag,验证通过的情况下才会继续比较 Last-Modified,最后才决定是否返回 304

  • 304 不也发送了请求吗,为什么会快?

虽然 304 也发送了一次请求,但服务器只会返回报文的头部信息,主体部分将不会返回,报文的大小和请求时间大大减少,于是就快了。

http 缓存的不同来源

  • from disk cache(从磁盘中获取缓存资源)

  • from memory cache(从内存中获取资源)

注意:当退出进程时,磁盘的数据不会被清空,而内存会。

不同的刷新方式

  • 在打开控制台的情况下,长按刷新图标(1-2秒),选择相应的刷新方式即可

  • 通过 F5 刷新,会忽略 Expires / Cache-Control 的设置(其实是加上了 Cache-Control: max-age=0 的请求字段),然后向服务器发送请求,而 Last-Modified / Etag 还是有效的,服务器会根据情况判断返回 304 还是 200

  • 通过 Ctrl+F5 进行强制刷新的时候,缓存将失效,会重新向服务器请求资源(当然不同浏览器和不同操作系统的刷新操作可能不一样)

需要注意的是

  • post 请求和经过 https 安全加密的请求不会被缓存

  • Cache-Control: no-cache 这个很容易让人误以为是响应不被缓存(我就是这样认为的)。实际上 no-cache 是会把数据缓存到本地的,只不过会被浏览器忽略,重新向服务器获取文件。而 Cache-Control: no-store 这个才是响应不被缓存的意思

  • 对于同一个资源,不同服务器生成的 Etag 可能不相同(生成规则由服务器决定,当然你可以自己修改服务器端 Etag 的生成方式)

  • 资源更新时,为防止用户获取信息不及时,我们可以在资源 uri 后面附加一些信息,如版本号、md5 和修改时间等

小技巧

  • 打开控制台,在 Network 那里把 Disable cache 前面打上勾,就可以禁止缓存了

  • 可以尝试在浏览器的无痕模式下进行开发或者做其它事情 ^_^ 嘿嘿 ~


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《浅谈 http 缓存》的版权归原作者「梅沙Fex」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注梅沙Fex微信公众号

梅沙Fex微信公众号:gh_f8cd41896475

梅沙Fex

手机扫描上方二维码即可关注梅沙Fex微信公众号

梅沙Fex最新文章

精品公众号随机推荐