缓存

缓存(cache),原始意义是指访问速度比一般随机存取存储器(RAM)快的一种高速存储器,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术。缓存的设置是所有现代计算机系统发挥高性能的重要因素之一。

WEB缓存

Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页

  • 客户端缓存

    浏览器缓存

  • 服务端缓存

    Nginx / Redis / Memcached等

    浏览器缓存

  • 概念

是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器从本地磁盘显示文档,加速页面的阅览。
浏览器缓存是成本最低的一种缓存实现,他可以减少网络带宽消耗、降低服务器压力、减少网络延迟,加快页面打开速度

  • 缓存相关头信息

Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高

header 说明
Expires 缓存过期的日期和时间
Cache-Control 设置和缓存相关的配置信息
Last-Modified 请求资源最后修改时间
ETag 请求变量的实体标签的当前值,比如文件的MD5值
If-Modified-Since 客户端再次发起请求时,携带上次请求返回的Last-Modified值
If-None-Match 客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值

Nginz静态资源缓存 - 图1

  1. 用户首次通过浏览器发送请求到服务端获取数据,客户端是没有对应的缓存,所以需要发送request请求来获取数据;
  2. 服务端接收到请求后,获取服务端的数据及服务端缓存的允许后,返回200的成功状态码并且在响应头上附上对应资源以及缓存信息;
  3. 当用户再次访问相同资源的时候,客户端会在浏览器的缓存目录中查找是否存在响应的缓存文件
  4. 如果没有找到对应的缓存文件,则走(2)步
  5. 如果有缓存文件,接下来对缓存文件是否过期进行判断,过期的判断标准是(**Expires**).
  6. 如果没有过期,则直接从本地缓存中返回数据进行展示
  7. 如果Expires过期,接下来需要判断缓存文件是否发生过变化
  8. 判断的标准有两个,一个是ETag(Entity Tag),一个是Last-Modified
  9. 判断结果是未发生变化,则服务端返回304,直接从缓存文件中获取数据
  10. 如果判断是发生了变化,重新从服务端获取数据,并根据缓存协商(服务端所设置的是否需要进行缓存数据的设置)来进行数据缓存。

浏览器缓存过程分析

浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中。
浏览器根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强制缓存协商缓存
Nginz静态资源缓存 - 图2

  1. 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
  2. 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

强制缓存

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程

  • 强制缓存规则

当浏览器向服务器发送请求的时候,服务器会将缓存规则放入HTTP响应的报文的HTTP头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Conctrol的优先级比Expires高。

  • Expires

Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求的结果缓存的到期时间,即再次发送请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。到了HTTP/1.1,Expires已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间服务端返回的时间做对比,如果客户端与服务端的时间由于某些原因(时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存直接失效,那么强制缓存存在的意义就毫无意义。

  • Cache-Control | 参数 | 说明 | | —- | —- | | public | 所有内容都将被缓存(客户端和代理服务器都可缓存) | | private | 所有内容只有客户端可以缓存,Cache-Control的默认取值 | | no-cache | 客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定 | | no-store | 所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存 | | max-age=xxx (xxx is numeric) | 缓存内容将在xxx秒后失效 |

  • 强制缓存种类

强制缓存的情况主要有三种

  1. 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求

Nginz静态资源缓存 - 图3

  1. 存在该缓存结果和缓存标识,但是结果已经失效,强制缓存失效,则使用协商缓存

Nginz静态资源缓存 - 图4

  1. 存在该缓存结果和缓存标识,且该结果没有还没有失效,强制缓存生效,直接返回该结果.

Nginz静态资源缓存 - 图5

协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:Last-Modified / If-Modified-SinceEtag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。

  • Last-Modified

Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间

  • If-Modified-Since

是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件

  • 协商缓存种类
  1. 协商缓存生效,返回304

Nginz静态资源缓存 - 图6

  1. 协商缓存失败,返回200和请求结果

Nginz静态资源缓存 - 图7

Nginx设置浏览器缓存

Nginx在响应头中添加:Cache-Control、Expires头实现浏览器缓存设置。

  • expires指令

expires:该指令用来控制页面缓存的作用。可以通过该指令控制HTTP应答中的“Expires”和”Cache-Control”

语法 expires [modified] time
expires epoch|max|off;
默认值 expires off;
位置 http、server、location
  1. time:可以整数也可以是负数,指定过期时间,如果是负数,Cache-Control则为no-cache,如果为整数或0,则Cache-Control的值为max-age=time;
  2. epoch: 指定Expires的值为’1 January,1970,00:00:01 GMT’(1970-01-01 00:00:00),Cache-Control的值no-cache
  3. max:指定Expires的值为’31 December2037 23:59:59GMT’ (2037-12-31 23:59:59) ,Cache-Control的值为10年
  4. off:默认不缓存。
    • add_header指令

add_header指令是用来添加指定的响应头和响应值。

语法 add_header name value [always];
默认值
位置 http、server、location…

Cache-Control作为响应头信息,可以设置如下值:

指令 说明
must-revalidate 可缓存但必须再向源服务器进行确认
no-cache 缓存前必须确认其有效性
no-store 不缓存请求或响应的任何内容
no-transform 代理不可更改媒体类型
public 可向任意方提供响应的缓存
private 仅向特定用户返回响应
proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=<秒> 响应最大Age值
s-maxage=<秒> 公共缓存服务器响应的最大Age值
  • 配置案例 ```nginx server{
    1. listen 8075;
    2. server_name localhost;
    3. expires 600;
    4. add_header Cache-control max-age=800;
    5. location /gzip {
    6. root /home/nginx/html;
    7. }
    }

``` 响应头有Cache-Control:

image.png