• Nginx 如何配置缓存?
  • 发布于 2个月前
  • 207 热度
    0 评论
前言

缓存是什么,为什么要学习 Nginx 如何配置缓存?我们知道,在性能优化中,缓存是其中非常重要的一环。学会缓存,可以提高用户的体验,减轻服务器的压力,如果对其不了解,也许在平时的开发中,遇到缓存问题,你也许会很苦恼。本文主要介绍 Nginx 客户端如何命中本地的缓存。


强缓存
Cache-Control 字段:HTTP1.2 产物
描述
no-store 禁止缓存(强缓存和协商缓存),客户端不存储任何值
no-cache 禁止强缓存,需要重写验证(可以理解为 禁止强缓存,启用协商缓存)
private 私有缓存,禁止中间人(比如CDN等代理缓存)
public 共享缓存,允许中间人缓存
max-age 资源可以被缓存的最大时间,单位:秒,是一个相对时间,优先级高于 Expires
s-maxage 用于共享缓存,单位:秒,如果在其有效期内,不去访问CDN等。s-maxage会覆盖 max-age 和 Expires
must-revalidate 缓存使用陈旧资源时,必需先验证状态
location /test {
  add_header Cache-Control "private, max-age=25920000";#开启私有缓存 缓存1个月
}

Expires 字段:HTTP1.0 产物
它是 服务器返回的一个绝对时间,优先级低于 Cache-Control
location /test {
  add_header Expires "10d";#缓存10天
}
协商缓存
我们知道,Nginx 默认是开启了协商缓存的,这里我们说一下如何关闭协商缓存
协商缓存这里主要分两种:
Etag 强校验器,根据文件内容和最后修改的时间生成的一段 hash字符串
Last Modified 弱校验器,它的值是 资源最后修改的时间,单位:秒

关闭 Etag
location /test {
  etag off;
}
关闭 Last_Modified
location /test {
  add_header Last-Modified '';
  if_modified_since off;
}

正常情况下,不建议关闭协商缓存


Pargma
http1.0 产物;优先级高于 Cache-Control/Expires;它的存在目的是向后兼容
add_header Pargma 'no-cache'; #禁止缓存

实践场景
在实际开发中,需要考虑一个常见的问题 那就是如何做到,在更新版本的时候,尽可能命中缓存的同时,让客户端本地的缓存失效

可行的方案是:
.HTML 使用协商缓存

.css、js、图片等资源,使用强缓存。配合webpack的文件指纹策略,打包的时候文件名带上hash值,这样有改动,hash值就会发生变化,达到让客户端缓存失效的目的


原因分析
为什么以上的方案,可以在更新版本的时候,适时的让客户端本地缓存失效呢?主要是两点,1. HTML 使用协商缓存,那么每次都会发送 请求到服务器,验证HTML是否发生了修改,如下HTML内容

可以看到,这HTML中,引入了通过webpack打包并在文件名上加上了hash值,这样,如果js、css等文件内容修改了,webpack重新打包后,hash值就会发生变化,导致 HTML 也跟着发生了变化

2.HTML 就会返回新的资源,虽然js/css/图片等资源使用强缓存,但是hash值变了,js/css/图片等资源的请求路径就发生了变化,
也就会发送新的请求,不会命中之前缓存,这样就可以在更新版本时,让客户端缓存自动失效

Nginx 配置:
server {
  listen 80;
  server_name 127.0.0.1;
  root /opt/nginx/frontEnd;

  # 压缩配置
  gzip on;
  gzip_comp_level 6;
  gzip_min_length 1k;
  gzip_types image/png image/jpeg image/gif image/svg+xml application/javascript;
  gzip_vary on;

  # 缓存相关字段的设置
  location /test {
    index index.html index.htm;
    # js、css、字体、图片等资源启用强缓存
    if ($request_uri ~* .*[.](js|css|map|jpg|png|svg|ico)$) {
      add_header Cache-Control "public, max-age=25920000";#非html缓存1个月
      add_header Expires "30d";
    }
    # HTML 启用协商缓存
    if ($request_filename ~* ^.*[.](html|htm)$) {
      add_header Cache-Control "public, no-cache";
    }
  }
}

Vary 字段
HTTP 内容协商机制:我们知道,除了私有缓存之外,还有共享缓存,共享缓存包括,CDN缓存、代理缓存、反向代理缓存、负载均衡缓存等等,那么有时候,我们就会想,像这种有中间人的代理缓存,该如何区分呢?比如有的低版本客户端,不支持压缩版本的代码,但是代理缓存有压缩的和没有压缩的代码版本,这时候该如何分发资源呢

Vary 可以指定代理缓存服务器返回给客户端正确的资源,它是通过以下方式实现的:
在客户端请求头中,携带 User-Agent 和 Cookie,服务端可以根据 User-Agent 和 Cookie
返回特定的资源,并在响应头中携带 Vary User-Agent Cookie,如果资源有被代理缓存,那么代理缓存服务器会根据响应头的 Vary 字段,返回缓存在代理缓存中正常的资源 给客户端
除此之外,内容协商还包括 Accept 字段


请求头字段 描述 响应头字段
Accept 告知服务器发送何种类型的媒体数据 Content-Type
Accept-Language 告知服务器发送何种语言 Content-Language
Accept-Charset 告知服务器发送何种字符集 Content-Type
Accept-Encoding 告知服务器采用何种压缩方式 Content-Encoding


用户评论