我们应该从两个角度来看http的缓存:缓存控制 和 缓存校验。
缓存控制:控制缓存的开关,用于标识请求或访问中是否开启了缓存,使用了什么样的存方式。
缓存校验:如何校验缓存,缓存的有效期,如何确定缓存是最新的。

一、缓存控制

  http中控制缓存开关的字段有两个:Pragma 和 Cache-Control。

  Pragma已经基本淘汰,下文我们重点关注 Cache-Control 。

  在介绍之前,我们先说明一下比较容易忽略的俩个点:

  1、符合缓存策略时,服务器不会发送新的资源,但不是说客户端和服务器就没有会话了,客户端还是会发请求到服务器的。

  2、Cache-Control除了在响应中使用,在请求中也可以使用。如下图:(在开发者工具中,禁用缓存)

同时在Response Headers中也能到Cache-Control字段,这是服务端设置的,如下图:

Cache-Control字段:

请求中使用Cache-Control 时,它可选的值有:

响应中使用Cache-Control 时,它可选的值有:

在Cache-Control 中,这些值可以自由组合,多个值如果冲突时,也是有优先级的,而no-store优先级最高。

public和private的选择

  如果你用了CDN,你需要关注下这个值。CDN厂商一般会要求cache-control的值为public,提升缓存命中率。如果你的缓存命中率很低,而访问量很大的话,可以看下是不是设置了private,no-cache这类的值。如果定义了max-age,可以不用再定义public,它们的意义是一样的。

 哪里设置Cache-Control

  以LNMP的环境为例,一次响应经历的过程是:php-cgi解析代码并执行,将结果返回给nginx,如果nginx前面有反向代理,则会经过一次反向代理服务器,所以cache-control可能会在nginx,php-cgi,php代码,反向代理服务器这些地方地方设置。在php.ini中,有个参数是session.cache_limiter,需要注意下。

在nginx中有个很常见的配置:

location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
expires 30d;
}

  这个指令等同于cache-control: max-age=2592000,同时你会在响应头部看到一个etag字段,这是由于nginx默认开启,如果要关闭可以增加个配置etag off。etag就是我们接下要看的缓存校验字段。

二、缓存校验

  在缓存中,我们需要一个机制来验证缓存是否有效。比如服务器的资源更新了,客户端需要及时刷新缓存;又或者客户端的资源过了有效期,但服务器上的资源还是旧的,此时并不需要重新发送。缓存校验就是用来解决这些问题的,在http 1.1 中,我们主要关注下Last-Modified 和 etag 这两个字段。

Last-Modified
  服务端在返回资源时,会将该资源的最后更改时间通过Last-Modified字段返回给客户端。客户端下次请求时通过If-Modified-Since或者If-Unmodified-Since带上Last-Modified,服务端检查该时间是否与服务器的最后修改时间一致:如果一致,则返回304状态码,不返回资源;如果不一致则返回200和修改后的资源,并带上新的时间。

If-Modified-Since和If-Unmodified-Since的区别是:
If-Modified-Since:告诉服务器如果时间一致,返回状态码304
If-Unmodified-Since:告诉服务器如果时间不一致,返回状态码412

etag
  单纯的以修改时间来判断还是有缺陷,比如文件的最后修改时间变了,但内容没变。对于这样的情况,我们可以使用etag来处理。
  etag的方式是这样:服务器通过某个算法对资源进行计算,取得一串值(类似于文件的md5值),之后将该值通过etag返回给客户端,客户端下次请求时通过If-None-Match或If-Match带上该值,服务器对该值进行对比校验:如果一致则不要返回资源。
  If-None-Match和If-Match的区别是:
  If-None-Match:告诉服务器如果一致,返回状态码304,不一致则返回资源
  If-Match:告诉服务器如果不一致,返回状态码412

总结
  缓存开关是: pragma, cache-control。
  缓存校验有:Expires,Last-Modified,etag。
  从状态码的角度来看,它们的关系如下图:

  

  cache-control的各个值关系如下图:

  

最新文章

  1. MySQL InnoDB表--BTree基本数据结构
  2. 【2016-11-7】【坚持学习】【Day22】【工作流引擎设计--执行用户】
  3. Linux上性能异常定位以及性能监控
  4. 深入Java集合学习系列:HashMap的实现原理
  5. CSS3之选择器
  6. 跨线程调用控件之MethodInvoker
  7. web工作方式,浏览网页,打开浏览器,输入网址按下回车键,然后会显示出内容,这个过程是怎样的呢?
  8. Hybrid App开发之JavaScript基础
  9. 从零认识Java Package
  10. ORACLE PL/SQL编程:把触发器说透
  11. es6 中的 symbol
  12. 基于ZigBee和STM32的智能家居控制系统的设计与实现(三)
  13. rpc框架 SimpleXMLRP
  14. [Selenium]验证点了某个Button之后无反应
  15. 布线问题 (NYOJ38)
  16. poj 2981 Strange Way to Express Integers (中国剩余定理不互质)
  17. python多线程的两种写法
  18. [SinGuLaRiTy] 高一下半期测试
  19. 51nod1347(简单逻辑)
  20. 小程序-支持的最小像素px

热门文章

  1. 在RedHead中安装Oracle
  2. C# 进程 与 线程
  3. Git 理解修改
  4. 文件的读取(txt文件)
  5. android如何在标题栏设置返回返回图标返回到另一个activity
  6. TP5给request对象动态绑定属性
  7. ZooKeeper基本介绍
  8. Java集合学习(4):HashTable
  9. Spark广播变量和累加器
  10. 记使用pyspider时,任务不执行的问题原因:save太大。