上一章介绍了整个HTTP结构中的代理这一环节,而在代理里面甚至是整个HTTP结构中,缓存是最重要的代理.所以这一章就专门介绍了为什么需要缓存,缓存的基本术语以及缓存的工作流程和如何操作缓存.
7.1 为什么需要缓存
7.1.1 冗余数据传输
- 为什么会产生冗余传输
- 多个客户端请求同一服务器,服务器会把相同的资源单独发送到每一个客户端
- 如果把缓存放到客户端的路由器上,那么同一路由器所有电脑的请求都不需要服务器传输了
7.1.2 带宽瓶颈
- 为什么会有瓶颈
- 本地网络一般是100M/s,而服务器下行带宽一般只有几M/s
- 从服务器请求资源肯定只有几M/s
- 如果把资源缓存在本地网络,那么速度就是100M/s了
7.1.3 瞬时拥塞
- 什么是瞬时拥塞
- 就是在重大情况或事件发生时,网络访问量突然激增,导致网络卡.比如双11,明星离婚
7.1.4 距离时延
- 为什么会有距离时延
- 数据通过电波/光来传输,但是光本身的速度是限的.
- 如果客户端和服务器在地球的2端,光来回跑,根据请求的多少,会导致几十ms甚至几百ms的延时
- 如果算上中间路由和代理的损耗,时间更长
7.2 有关缓存的术语
7.2.1 缓存命中
- 什么是缓存命中
- 请求达到缓存代理,并由缓存资源提供响应
7.2.2 缓存未命中
- 什么是缓存未命中
- 请求达到缓存代理,但没有合适的缓存资源,请求被转发到原始服务器
7.2.3 缓存再验证
-
什么是缓存再验证
- 代理向原始服务器发送请求验证当前缓存是否需要更新
-
为什么需要再验证/新鲜度检测
- 原始服务器上的资源有可能已经更新或者被删除了
- 要保证缓存和原始资源一致
-
什么时候进行再验证
- 在客户端发起请求后
- 并且缓存资源变得很旧的时候向服务器进行验证
-
再验证的几种结果
- 再验证命中
- 验证后发现资源未发生变化
- 更新缓存头部信息
- 再验证未命中
- 验证后发现资源已经变化
- 更新整个缓存,包括头部和主体
- 对象被删除
- 服务器的资源已经删除
- 删除缓存
- 再验证命中
7.2.4 命中率
- 什么是缓存命中率
- 所有请求中,有多少响应是从缓存提供
- 什么是字节命中率
- 缓存提供的字节在所有请求的字节中所占的比例
- 为什么需要字节命中率
- 因为有些请求虽然少,但体积可能非常大
- 所以用字节命中率统计流量非常有用
- 怎么区分响应是否来自缓存
- 响应中的Date首部如果小于当前时间
- 通过响应中的Date和Age首部判断
7.3 缓存的结构
-
缓存有哪几种分类
- 私有缓存: 如浏览器自带的缓存
- 公有缓存: 如CDN
-
缓存有哪几种结构
- 层次结构
- 网状结构
-
层次结构和网状结构的区别
- 层次结构是串联的,1层没找到缓存就向父级缓存再找直到服务器
- 网关结构是蜘蛛网形的,有可能被转发到任意的缓存上获取资源
-
网状缓存有哪些功能
- 在父缓存和原始服务器之间进行选择
- 动态选择父缓存
- 允许其他缓存对访问本地缓存
-
什么是对等缓存
- 将互联网上的其他缓存联合起来,组成一个巨大的缓存网
- 资源互相共享的缓存网就是对等缓存
- 其中的每一个缓存都是兄弟缓存
- 如ICP,HTCP
7.4 缓存的处理步骤
缓存的处理步骤和代理的处理步骤是一样的7步,只是 细微的关于新鲜度检测这一块需要单独说明一下.
- 接收请求
- 解析请求
- 查找资源
- 查找资源的步骤
- 先找本地缓存
- 如果没有的话去服务器/父缓存中取
- 查找资源的步骤
- 新鲜度检测
- 哪些情况下需要检测新鲜度
- 过期时间超过了限值
- 客户端要求检测
- 哪些情况下需要检测新鲜度
- 构建响应
- 响应包含哪些内容
- 原始资源的头部
- 原始资源的主体
- 缓存相关信息,如Age,Cache-Control等
- 响应包含哪些内容
- 发回响应
- 记录日志
7.5 如何保持缓存的新鲜度
-
怎么判断文档是否过期
- Cache-Control: max-age
- Expires
-
为什么推荐使用max-age
- max-age是指Date之后的多长时间
- Expires是指具体的一个时间值
- 不同的服务器解析时间值的方法可能不一样,所以用Expires可能会导致差异
-
设置过期时间的目的
- 服务器资源随时可能变化
- 给个到期时间提醒缓存需要验证是否发生了变化
-
再验证的工作流程
- 如果资源发生了变化 -> 获取新的缓存 -> 转发给客户端
- 如果资源未变化 -> 获取新的首部 -> 转发给客户端
-
为什么要用GET条件方法进行再验证
- 发送一个带条件的GET方法
- 只有满足条件时才返回实体资源
- 可以减少网络流量
-
用于条件GET的2个首部
- If-Modified-Since:
- If-None-Match:
-
IMS的不足之处
- 有些文件会周期性的重写,变化的只是日期,内容不会变化,会导致重新更新缓存
- 有些文件虽然更新了内容,但只是变了些无关紧要的部分,如注释,也会导致缓存更新
- 有些文件是实时更新的,过期时间是秒就无法满足要求了
-
什么是缓存验证器
- 除了过期时间以外,还可以通过实体标签验证缓存资源
- 这两个都属于缓存验证器
-
为什么需要区分强弱验证器
- 有些资源发生了不重要的变化,不需要重新更新缓存
- 这种情况只更新强标签,而不用更新弱标签
- 以弱标签为判断依据的缓存就没必要更新了
-
弱标签的表现形式
- 会在实体标签前面加上一个
W/用于区分
- 会在实体标签前面加上一个
-
什么情况下使用IMS和实体标签验证
- 响应只返回了Last-Modified的时候使用IMS
- 响应只返回了ETag时使用实体标签验证
- 如果都返回了,两种方式都要使用
7.6 服务器怎么控制代理缓存
-
Cache-control: no-store
- 禁止缓存
-
Cache-Control: no-cache
- 可以缓存,但是每次请求都必须进行新鲜度检测
-
Pragma: no-cache
- 和no-cache一致
- 只是为了兼容HTTP/1.0
-
Cache-Control: max-age=100
- 最大存活时间
-
Cache-Control: s-maxage=100
- 作用同max-age
- 只适用于共享缓存
-
Expires:
- 具体的某个时间点过期
-
Cache-Control: must-revalidate
- 没搞懂他和no-cache的区别
-
什么是试探性过期
- 当服务器没有提供Expires也没有提供Cache-Control: max-age时
- 代理自动推算过期时间
-
设置试探性过期的几种方式
- 通过算法估算
- 设置成一个固定值
7.7 客户端如何控制缓存
- Cache-Control: max-stale
- Cache-Control: max-stale=s
- Cache-Control: max-fresh=s
- Cache-Control: max-age=s
- Cache-Control: no-cache
- Cache-Control: no-store
- Cache-Control: only-if-cached
- Pragma: no-cache
7.8 如何设置缓存
7.8.1 Apache
这个就不用做笔记了吧.如果以后要搞全栈,那就要专门看Apache的书了
7.8.2 HTML元信息标签HTTP-EQUIV
- HTTP-EQUIV是什么
- 就是一个HTML元素
- 专门用于指定该HTML文档的缓存信息
<meta http-equiv="Cache-Control" content="no-store">
- 为什么不推荐使用HTTP-EQUIV
- 很少有服务器实现这个功能
- 浏览器虽然实现了这个功能,但和代理实现的逻辑可能不一样
7.9 新鲜度的详细算法
暂时涉及到算法的部分,先全部跳过吧
7.10 缓存和广告
-
为什么广告商讨厌缓存
- 广告商一般是根据广告展现次数收费
- 有了缓存之后,流量都从缓存走了,不经过广告商
- 就收不到广告费啦
-
如何解决缓存拦截流量
- 设置no-cache
- 通过CGI网关提供广告
- 重写广告URL
- 在缓存上配置,每次都进行再验证
- 将命中日志报告发给服务器
- 使用HTTP/1.1中的Meter首部