Nginx 缓存浅析

Nginx 缓存问题

问题

Nginx 设置协商缓存 ,由于微信扫码、打开链接时与浏览器在地址栏输入回车表现不同,微信H5在强缓存过期前&只开启协商缓存时,会只走缓存(实际上不会发送http请求到后端,而是只走缓存)。
除非刷新,否则由于拿到过期文件导致js、css资源 404报错 或者 旧js文件而非新版代码。

其他网站解决方案

  • 腾讯云:

    • js
      • jquery 等库设为 max-age=31536000 \ expires 一年
      • 配置文件 不设置缓存
      • 其他资源设置 max-age=600 \ expires 10分钟
    • css

      • base 基础配置 max-age=31536000 \ expires 一年

      • 其他资源 max-age=3600 \ expires 1小时

    • img

      • svg + 部分img: max-age=600 \ expires 10分钟
      • max-age=3600 \ expires 1小时
      • 这里没有看出来怎么分的
    • doc 不设置缓存

  • google

    • 与腾讯云差不多,没用单页开发,js文件大部分为 public, max-age=31536000
    • Doc 不设置缓存
  • 知乎

    • js css img 使用单页开发,max-age=31536000
    • doc 文件不设置缓存
  • 结论

    • 对doc、js配置文件不设置缓存,其他均设置为最大 max-age=31536000

配置方式

nginx默认开启etag,无需手动开启。
直接在项目的 nginx 配置中添加即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
location ~ .*\.(js|css|gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}

location = /index.html {
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires -1s;
etag off;
}

# config 文件,如没有可以不用加
location = /yilearnConfig.js {
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires -1s;
etag off;
}

平滑重启nginx
nginx -s reload 有时候提示绑定端口问题,重启无效,所以用下面这个方法重启
查看ID ps -ef|grep nginx
kill -HUP 1 // 1 为查找到的nginx id

  • 在使用不受信任的证书时(一般是自签名证书),缓存不会生效。

参考文章

第一篇主要了解强缓存和协商缓存这两个常用缓存方式,一般两个一起使用
第二篇可以了解到HTTP1.0时代缓存方式及不同缓存的优缺点

https://zhuanlan.zhihu.com/p/54314093
https://www.cnblogs.com/kevingrace/p/10459429.html

QA

  1. 多集群部署,etag是否会变化,导致缓存不生效

    https://github.com/wadezhan/billfeller.github.io/issues/91

nginx生成etag的算法是以文件最后修改时间截+文件内容长度为唯一标识符;
文件最后修改时间截 在前端docker镜像编译时确定,镜像部署时也不会被修改,所以集群部署也不会变化。
经测试,在不同机器上部署同一镜像,etag 和 Last-Modified 不会变化

  1. 我们只开了协商缓存,微信会给我们设置强缓存的头?还是表现为类似强缓存一样的情况?
    表现为类似强缓存一样的情况
  1. 这种类似的表现有固定的过期时间还是无限大还是未知? 目前看到的情况是 未知。
    有时候出现隔一两天都走缓存的情况。但是前几天测试出现过几分钟后拿了新文件(非登录过期)
  1. 微信 Android 和 iOS 都会有这个问题是吧?
    理论上都有,只是这几天只测出来ios的,以前是测出华为的有,不同机型表现不太一样