HTTP 缓存,对于前端的性能优化方面来讲,是非常关键的,从缓存中读取数据和直接向服务器请求数据,完全就是一个在天上,一个在地下。

我们最熟悉的是 HTTP 服务器响应返回状态码 304,304 代表表示告诉浏览器,本地有缓存数据,可直接从本地获取,无需从服务器获取浪费时间。

至于为什么被缓存,如何命中缓存以及缓存什么时候生效的,我们却很少在实际开发中去了解。今天小鹿借助动画形式来从根上理解 HTTP 缓存机制及原理。

为什么会有缓存?

单纯的从计算机角度去说,比较抽象,咱们看一个实际的例子。比如,我们通常喜欢把没看完的书放在书架上,而看完以及没有看的书放在箱子中保存。

如果我们把所有的书保存在箱子中,每次看书都要去箱子中找,所以非常麻烦和耗时(这里的箱子,可以想象成服务器)。

当我们开始看新书时,第一次从箱子中取出,看了一半,然后我们直接放到书架上,当下次再看书的时候,直接从书架中取出,这里的书架,就是我们下边要讲到的缓存(一个缓存仓库)。

缓存的“龟”则

当浏览器发出请求到数据请求回来的过程,就像是上述中的取书过程。

浏览器在加载资源时,根据请求头的Expires 和 Cache-control 判断是否命中强缓存,是则直接从缓存读取资源,不会发请求到服务器。

如果没有命中强缓存,浏览器一定会发送一个请求到服务器,通过 Last-Modified 和 Etag 验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,依然是从缓存中读取资源。

如果前面两者都没有命中,直接从服务器加载资源。

动画演示

HTTP 缓存分类

上述讲到,HTTP 是有“龟”则的,根据浏览器是否向服务器发起请求来分为强缓存和协商缓存

1、强缓存

强缓存的意思就是不向服务器发起请求的缓存,也就是本地强制缓存。浏览器想要获取特定数据的时候,首先会检查一下本地的缓存是否存在该数据,如果存在,就直接在本地获取了,如果不存在,就向服务器所要该数据。

详细请求过程如下动画所示:

那么问题来了,如果我们想使用强缓存,那怎么判断缓存数据什么时候失效呢?

当浏览器向服务器请求数据的时候,服务器会将数据和缓存的规则返回,在响应头的 header 中,有两个字段 Expires和Cache-Control。

Expires

1expires: Wed, 11 Sep 2019 16:12:18 GMT

在响应头中 Expires 字段的意思是,当前返回数据的缓存到期时间戳。当浏览器在进行请求的时候,会那浏览器本地的时候和这个时间做对比,判断资源是否过期。

但是上述存在一个问题就是,如果我手动改变了电脑的时间,那么就会出现问题,这也是 HTTP1.0 中存在的问题。

Cache-Control

为了解决这个问题,在 HTTP1.1 中增加了 Cache-Control 这个字段。

1Cache-Control:max-age=7200

服务器和客户端说,这个资源缓存只可以存在 7200 秒,在这个时间段之内,你就可以在缓存获取资源。

如果 Expire 和 Cache-control 两者同时出现,则以 Cache-control 为主

除此之外,cache-control 还有其他字段可以使用。

1cache-control: max-age=3600, s-maxage=31536000
  • Public:只要为资源设置了 public,那么它既可以被浏览器缓存,也可以被代理服务器缓存;

  • Private(默认值):则该资源只能被浏览器缓存。

  • no-store:不使用任何缓存,直接向服务器发起请求。

  • no-cache:绕开浏览器缓存(每次发起请求不会询问浏览器缓存),而是直接向服务器确认该缓存是够过期。

2、协商缓存

浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。

再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通知客户端比较成功,可以使用缓存数据。

1// 命中缓存的响应字段2Request Method:GET3Status Code: 304 Not Modified

怎么来识别协商缓存的?主要通过报文头部 header 中的Last-Modified,If-Modified-Since 以及ETag、If-None-Match 字段来进行识别。

Last-Modified 

Last-Modified 字段的意思是服务器资源的最后修改时间。第一次请求服务器,服务器的头部字段可增加这个字段,用于设置协商缓存。

1Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT

当浏览器再次发起请求的时候,首部字段增加 If-Modified-Since 本地时间戳字段发给服务器。

1If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

服务端接收到请求之后,就拿 If-Modified-Since 字段值和本身的过期时间对比。

如果请求头中的这个值小于最后修改时间,返回的 304 响应,让其在本地浏览器缓存取出数据。如果时间过期,并在 Response Headers中添加新的 Last-Modified 值返回给浏览器。

但是 Last-Modified 存在一个局限性,有以下两种情况:

不该请求,还会请求。编辑了文件,文件内容没有变,但是服务器确认为我们改动了文件,所以重新设置了缓存时间,当做新请求返回给浏览器。

该请求,反而没有请求。修改文件速度很快,快过 If-Modified-Since 字段时间差的检测,文件虽然改动了,但是并没有重新生成新的资源。

ETag

ETag 代表的意思是标识字符串。由于上述 Last-Modified 字段存在的缺陷,所以在 HTTP / 1.1  我们对资源进行内容编码,只要内容被改变,这个编码就不同。

和上述请求原理一样,浏览器首次发起请求,然后服务器在响应头返回一个标识字符串。

1ETag: W/"2a3b-1602480f459"

浏览器再次发起请求,携带一个值相同的字符串。

1If-None-Match: W/"2a3b-1602480f459"

服务端接收到该字符串就会作对比,如果相同,则让其读取本地缓存,否则,将新的资源返回给浏览器端。

缓存位置

缓存的位置按照获取资源请求优先级,缓存位置依次如下:

  • Memory Cache(内存缓存)

  • Service Worker(离线缓存)

  • Disk Cache(磁盘缓存)

  • Push Cache(推送缓存)

Memory Cache

Memory 为内存缓存,是浏览器最先尝试命中的缓存,也是响应最快的缓存。但是存活时间最短的,当进程结束后,tab 标签关闭后,缓存就不存在了。

因为内存空间比较小,通常较小的资源放在内存缓存中,比如 base64 图片等资源。

Service Worker

Service Worker 是一种独立于主线程之外的 Javascript 线程。它脱离于浏览器窗体,因此无法直接访问 DOM。

可以帮我们实现离线缓存、消息推送和网络代理等功能。

Disk Cache

内存的优先性,导致大文件不能缓存到内存中,那么磁盘缓存则不同。虽然存储效率比内存缓存慢,但是存储容量和存储市场有优势。

Push Cache

它是最后一道缓存命中,属于 HTTP2 的内容。如果感兴趣的同学,可以先去了解了解。

-------------------------

❤️爱心三连击

如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:

  1. 点个「在看」,让更多的人也能看到这篇内容

  2. 欢迎关注我的5000+star文章合集 https://github.com/ljianshu/Blog,希望可以带给你点启发!

  3. 如果想进前端交流群一起探讨技术,请在后台回复「1

轻点在看,支持作者❤️

syslog 向内存中缓存_动画:深入浅出从根上理解 HTTP 缓存机制及原理!相关推荐

  1. 从根上理解高性能、高并发(五):深入操作系统,理解高并发中的协程

    本文原题"程序员应如何理解高并发中的协程",转载请联系作者. 1.系列文章引言 1.1 文章目的 作为即时通讯技术的开发者来说,高性能.高并发相关的技术概念早就了然与胸,什么线程池 ...

  2. syslog 向内存中缓存_内存问题排查手段及相关文件介绍

    5. 内存问题排查手段及相关文件介绍[重点] 对于内存问题排查,或者OOM问题排查,一般会涉及到如下文件,下面将如下文件的分析和设置介绍一下,这也是本文档的重点,后面排查内存信息还是要根据这些文件信息 ...

  3. syslog 向内存中缓存_漫谈缓存(Cache)、大规模芯片系统的存储层次结构优化以及开源仿真工具ZSim...

    这次的话题将从缓存开始,以一种易于理解的方式向大家呈现缓存的基本概念,然后拓展至大规模芯片系统的非均一访问延时的缓存访问问题,最后简要介绍一种缓存仿真工具--ZSim. 缓存的概念 处理器和内存之间存 ...

  4. 论坛分页频繁更新帖子缓存_如何实现频繁更改内容的“可缓存”分页

    论坛分页频繁更新帖子缓存 by Nikita Kozlov 由Nikita Kozlov 如何实现频繁更改内容的"可缓存"分页 (How to implement "ca ...

  5. raid配置ssd为缓存_一种基于SSDRAID阵列的多级缓存及缓存方法与流程

    本发明属于固态硬盘存储技术领域,更具体地,涉及一种基于SSD RAID阵列的多级缓存及缓存方法. 背景技术: 基于闪存的固态磁盘(Solid State Drives,SSD)以其优异的性能.非异失和 ...

  6. sql oltp_内存中的OLTP系列– SQL Server 2014上的数据迁移指南过程

    sql oltp In this article we will review migration from disk-based tables to in-memory optimized tabl ...

  7. linux刷新本地dns命令_在Linux/Windows/Mac上刷新DNS缓存的方法

    刷新dns缓存让你可以得到新的域名解析.当你无法正确访问一个新注册的域名时就可以刷新dns缓存试试.刷新dns缓存非常简单,任何时候都以进行.但是不同的系统,Windows.Mac OS和Linux上 ...

  8. 交换机分布缓存_交换机网络嗅探方法 如何欺骗交换机缓存

    嗅探(sniff),就是窃听网络上流经的数据包,而数据包里面一般会包含很多重要的私隐信息,如:你正在访问什么网站,你的邮箱密码是多少,你在和哪个MM聊QQ等等......而很多攻击方式(如著名的会话劫 ...

  9. php生成临时文件,使用PHP处理内存中的存档(无需在磁盘上创建临时文件)

    小编典典 我遇到了同样的问题,但最终找到了一个不太明显的解决方案,决定在这里分享. 我遇到了很棒的zip.lib.php/ unzip.lib.php脚本,它们phpmyadmin都位于"库 ...

最新文章

  1. QT 中 界面中消息的停留时间解决方案 以及 label 中字体大小和换行设置
  2. windows mobile设置插移动卡没反应_ETC不用时,能不能把卡拔下来
  3. 造完家怎么拆东西_地弹簧玻璃门怎么拆?地弹簧玻璃门拆除注意事项有哪些?...
  4. 【C++】C++类的学习(一)——初识类
  5. 使用System Center Essentials 2007查看计算机的软件清单
  6. 结构化数据上的机器学习大杀器XGBoost
  7. 使用Appium进行Android自动化测试遇到编译不成功的错误处理
  8. win10下能够用的键盘映射工具? win10 下按键像mac一样
  9. Forward Secrecy
  10. android 传感器应用
  11. 北京南天软件java工程师面试题
  12. h5新标签video详解
  13. Mockito 框架用于单元测试
  14. 【spring】PO,VO,DAO,BO,POJO,Bean之间的区别与解释
  15. ubuntu安装fcitx五笔拼音输入法
  16. 看“千人工程”事件有感
  17. java自定义包名和类名不可同名
  18. nodejs 事件轮训
  19. 将豆瓣排名前250爬取数据通过sqlite3存入数据库
  20. 商业数据分析的四个层次

热门文章

  1. 蚂蚁链发布新一代网络平台「FAIR」 区块链进入隐私计算原生时代
  2. CPU 明明 8 个核,网卡为啥拼命折腾一号核?
  3. 漫画 | 面试的我 VS 真实的我
  4. 博文强识|进阶企业大咖
  5. 甲骨文中国裁员已定,补偿为N+6;VMware联手云平台合作伙伴AsiaPac,闪耀狮城;对标英伟达,寒武纪新货曝光……...
  6. android系统手势app,8种iOS手势规定和14种android手势规定详解
  7. RabbitMQ的5种队列_路由模式_入门试炼_第8篇
  8. Vue + Spring Boot 项目实战(四):前后端结合测试(登录页面开发)
  9. spring boot 集成 log4j 解决与logback冲突问题
  10. Vue 自定义指令的注册方式和选项参数