先看一些概念性的术语:

命中率:由缓存提供服务的请求所占的比例被称为缓存命中率;

缓存未命中:其实就是一些到达缓存的请求没有副本可用,而被转发给原始服务器;

再验证:原始服务器上内容可能会发生变化,缓存需要对副本进行检测,看是否为最新的,这种“新鲜度检测”叫HTTP再验证;

缓存主要分为两类:

一,私有缓存

私有缓存是用户个人的缓存,Web浏览器中有内建的私有缓存,大部分浏览器将内容缓存到个人电脑的磁盘和内存中。这些缓存用来提供浏览器向前/向后、保存网页、查看源代码、离线浏览等功能。

二,公有代理缓存

公有缓存是多个用户使用,它是特殊的共享代理服务器,被称为缓存代理服务器,或被称为代理缓存。

缓存的基本步骤:

1,接收;

2,解析:将请求报文解析为片段;

3,查找;

4,新鲜度检测;

5,创建响应;

6,发送;

7,日志;

一,判断缓存是否过期:

1,cache-control: max-age=15400

max-age表示多少时间后过期,单位秒,这里是相对时间,既可以作为请求头,也可以作为响应头,如果请求头中设置max-age=0,表示立即过期,会进行新鲜度的校验,详细见后文。

还有一个s-maxage,仅适用于共享(公共)缓存

2,expires: Tue, 30 Jul 2019 04:59:34 GMT

表示什么时间后过期,这里是绝对时间,取决于用户当前系统时间,因此不建议单以这个为过期标准。

一般情况下,建议使用cache-control: max-age头,相对时间更好一些,如果两个标识都有,那么必须两个都过期了才算过期。

二,如果过期了,会进行新鲜度的校验:

当缓存资源过期时,缓存会向原始服务器发送一个条件请求GET,因为虽然当前缓存资源已经过期,但也有可能资源依然没有变化,所以不一定需要重新去获取资源,这时候就要做新鲜度的校验,对比缓存资源是否需要更新。

1,If-Modified-Since/Last-modified:Thu, 30 May 2019 11:44:49 GMT

这两个是搭配使用的,前者是请求头,后者是响应头,第一次返回数据时,响应头里会包含Last-modified字段,用来表示最近一次更新时间,当缓存资源过期时,缓存就会发送一个条件请求GET,请求头里带有If-Modified-Since,值就是Last-modified之前返回的值,如果检测发现服务器上资源文件最近修改时间和请求头里的这个时间一致,则不需要更新缓存,返回304状态码,这时候响应主体里是不会带有资源内容的,因为不需要更新,所以不返回,并重新更新缓存时间,就是上面说的cache-control: max-age和expires。如果不一致,则重新返回新的资源内容以及最近修改时间,并设置过期时间,状态码200.

2,If-None-Match/Etags: W/"d343901e56dedb646942d7f8d2a7df87"

对于大部分场景,Last-modified是满足的,但是对于一些特殊场景,那么就有问题了:

1️⃣亚秒级别的资源更新,时间相关的,因为Last-modified只能精确到秒级,所以无法精准;

2️⃣对于一些资源的更新,如果只是更新了一些无关紧要的小内容,那其实没必要重新更新缓存资源,我们允许继续使用旧的缓存,那这时候实际上就是一种弱检查;

Etags会返回一段hash的字符串,用来标识当前资源,如果缓存过期,那么If-None-Match就会带上Etags第一次返回过来的值,然后去和服务器上的tag作对比,如果发现不一致,则重新返回资源并更新缓存,如果没有变化,则返回304,更新缓存过期时间。这里示例代码里加了一个W,就表示这是一条弱检查。

但是大部分场景,我们还是使用If-Modified-Since/Last-modified来判断是否需要更新过期资源。

三,强制更新或取消缓存

这里还是用到cache-control头,这里作为请求头

no-store:禁止使用缓存,清除缓存资源,重新去原始服务器上去获取资源;

no-cache:在进行新鲜度校验之前,不能使用缓存。和no-store不一样的是,no-cache并不是不缓存,而是缓存了但是不使用,在新鲜度校验成功后才可以使用缓存;

must-revalidate:在缓存资源过期之后,必须进行新鲜度校验,这里是必须过期之后才起作用;过期后强制校验;(没什么用)

再补充一个stale-while-revalidate: 它表示允许缓存过期后的一段时间内继续使用,同时会发起一个异步新鲜度二次校验,如果资源更改了,那么下次访问的时候就能拿到一个新鲜的,但如果过期时间没有超过stale-while-revalidate给出的时间,第一次的时候一定是取的缓存,这种策略是用速度换取了内容的新鲜程度,需要谨慎使用。

这里补充一个Chrome里的知识点:

我们一般打开一张图片,如果是首次打开,这里就是一个正常的请求,状态码200,图片大小正常,size有值。

但是当我们关掉这个浏览器,再重新打开一个,再次访问刚刚的图片地址,状态码200,会发现这里的size变成了from disk cache,这里表示已经缓存到本地硬盘里中了,所以会直接读取硬盘里的缓存图片,然后返回的报文也是之前缓存的时候的报文。

当我们刷新这个页面,会发现状态码变成了304,size有值了,但是和第一次打开的时候不一样,那么根据之前讲的,304说明浏览器进行了缓存的新鲜度二次校验,那么我们可以猜测,浏览器在刷新的时候,会发一个cache-control: no-cache的请求,进行一个二次新鲜度校验,这里发现图片资源未改变,所以不会重新获取资源,而是继续读取本地缓存,所以状态码为304,而大小为什么不是原图大小,因为二次校验的时候,条件请求如果为否,则不会返回完整资源。

这里应该还有一个size情况是from memory cache,表示是从内存里读取的缓存,这里我没有找到截图,它和from disk cache的区别就是内存里的缓存优先级更高一些,但是如果浏览器关闭,则会清掉,而disk cache是永久性的,除非手动删除硬盘上的缓存,不然一直存在,浏览器关掉也在。所以整个校验流程是:

1,浏览器内存中读取缓存;

2,本地硬盘上读取缓存;

3,从服务器拉取数据,并缓存到本地硬盘和内存中;

end

HTTP系列:缓存的更多相关文章

  1. 《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU

    你知道的越多,你不知道的越多 点赞再看,养成习惯 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联 ...

  2. 《吊打面试官》系列-Redis常见面试题(带答案)

    你知道的越多,你不知道的越多 点赞再看,养成习惯 GitHub上已经开源,有面试点思维导图,欢迎[Star]和[完善] 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在 ...

  3. iOS图片加载速度极限优化—FastImageCache解析

    FastImageCache是Path团队开发的一个开源库,用于提升图片的加载和渲染速度,让基于图片的列表滑动 优化点 iOS从磁盘加载一张图片,使用UIImageVIew显示在屏幕上,需要经过以下步 ...

  4. iOS 图片加载速度极限优化—FastImageCache解析

    FastImageCache是Path团队开发的一个开源库,用于提升图片的加载和渲染速度,让基于图片的列表滑动起来更顺畅,来看看它是怎么做的.优化点iOS从磁盘加载一张图片,使用UIImageVIew ...

  5. 20191128 Spring Boot官方文档学习(9.9)

    9.9.数据存取 Spring Boot包含许多用于处理数据源的启动器. 9.9.1.配置自定义数据源 要配置自己的DataSource,请在配置中定义该类型的@Bean.Spring Boot可以在 ...

  6. prometheus远程写参数优化

    一.概述 prometheus可以通过远程存储来解决自身存储的瓶颈,所以其提供了远程存储接口,并可以通过过配置文件进行配置(prometheus.yml).一般情况下我们使用其默认的配置参数,但是为了 ...

  7. iOS 图片加载速度优化

    FastImageCache 是 Path 团队开发的一个开源库,用于提升图片的加载和渲染速度,让基于图片的列表滑动起来更顺畅,来看看它是怎么做的. 一.优化点 iOS 从磁盘加载一张图片,使用 UI ...

  8. Redis好文章推荐

    文章来源:掘金   作者:敖丙 Redis-避免缓存穿透的利器之BloomFilter <我们一起进大厂>系列- Redis基础 <我们一起进大厂>系列-缓存雪崩.击穿.穿透 ...

  9. 2020Java程序员架构师面试宝典,学习后面试必过,震惊,本人通过这篇教程,拿到了0个offer

    1. 引言 Java后端学习路线 <吐血整理>顶级程序员工具集 https://github.com/AobingJava/JavaFamily 跟上Java8 经历阿里.头条.腾讯等知名 ...

  10. CRL快速开发框架系列教程六(分布式缓存解决方案)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

随机推荐

  1. 9 16 模拟赛&关于线段树上二分总结

    1 考试时又犯了一个致命的错误,没有去思考T2的正解而是去简单的推了一下式子开始了漫漫找规律之路,不应该这样做的 为了得到规律虽然也打了暴力 但是还是打了一些不必要的程序 例如求组合数什么的比较浪费时 ...

  2. JS&ES6学习笔记(持续更新)

    ES6学习笔记(2019.7.29) 目录 ES6学习笔记(2019.7.29) let和const let let 基本用法 let 不存在变量提升 暂时性死区 不允许重复声明 块级作用域 级作用域 ...

  3. MySQL数据库高可用方案

    一.什么是高可用性: 高可用性=可靠性,它的本质就是通过技术和工具提高可靠性,尽可能长时间保持数据可用和系统运行,实现高可用性的原则,首先要消除单点故障,其次通过冗余机制实现快速恢复,还有就是实现容错 ...

  4. 利用 Python 写一个颜值测试小工具

    我们知道现在有一些利用照片来测试颜值的网站或软件,其实使用 Python 就可以实现这一功能,本文我们使用 Python 来写一个颜值测试小工具. 很多人学习python,不知道从何学起.很多人学习p ...

  5. 恢复HTML表格笔记

            表格         语法:          标记:            <table></table>:表示一个表格                属性: ...

  6. Java高级篇反射和注解

    反射是什么? 反射的作用?能带来什么好处? 反射的使用? 注解的使用? 注解和反射配合实战...

  7. css 命名规则 BEM!

    随着CSS的发展,使用CSS有语义化的命名约定和CSS层的分离,将有助于它的可扩展性,性能的提高和代码的组织管理.著作权归作者所有. BEM本质应该是一个css命名方案,最流行的命名规则之一就是BEM ...

  8. windows系统下python setup.py install ---出现cl问题,cpp_extension.py:237: UserWarning: Error checking compiler version for cl: 'utf-8' codec can't decode byte 0xd3 in position 0: invalid continuation byte

    将cpp_extension.py文件中的 原始的是   compiler_info.decode() try: if sys.platform.startswith('linux'): minimu ...

  9. 谁先执行?props还是data或是其他? vue组件初始化的执行顺序详解

    初入vue的朋友可能会疑惑,组件初始化的时候,created,props,data到底谁先执行? 今天,我就带大家从源码的角度看看到底谁先执行? 我们知道,vue是个实例 那我们就从new Vue() ...

  10. DES算法的python3实现

    DES原理 DES原理 这里不予以复述, 有很多优秀的博客 原理可以参考这篇博客 https://www.cnblogs.com/songwenlong/p/5944139.html DES实现 1. ...