讨论一下Nginx的缓存配置

测试前的准备

  越来越多人使用Nginx作为中间件,然后顺带使用了Nginx的缓存,我们来讨论一下Nginx的缓存。测试的架构图如下所示:

  用户,也就是我自己,使用的浏览器(浏览器disable cache)请求资源,通过修改中间Nginx的配置和源站的配置,来测试不同配置下,不同的缓存状态。

  我们先认识几个配置 :

  • Nginx配置中的inactiveproxy_cache_valid

  • 源站设置的头部ExpiresCache-contorl中的max-age s-max-age

Nginx缓存配置

proxy_cache_path /data/nginx_cache/bcsama levels=1:2 keys_zone=ddun:100m inactive=60s max_size=200m;

server{
...
    add_header          Cache-status $upstream_cache_status;
    proxy_http_version  1.1;
    proxy_set_header    Connection "";   
    
    location ~* \.php$ {
            proxy_no_cache      0;
            proxy_cache_bypass  0;
            proxy_redirect      off;
            proxy_cache         bcsama;
            proxy_cache_valid   200 304 30s;
            proxy_cache_key     $host$1$is_args$args;
            proxy_pass          http://bcsama;
        }
...
}

源站php设置

<?php
# header("Cache-Control: max-age=60");
header("Cache-Control: s-maxage=60");
header("Expires: Wed, 23 Nov 2017 06:41:00 GMT");
# header("Expires: 0");
echo "test cache";
?>

正式测试

第一次测试

配置

  • Cache-Control: s-maxage=60

  • Expires: 0 备注:Expires的值为0的时候,表示已经过期

  • proxy_cache_valid 30s

  • inactive=90s

请求过程:

请求第一次,        Cache-status MISS    
随后请求第二次,     Cache-status HIT    
30s过后请求第三次, Cache-status HIT    
65s过后请求第四次, Cache-status EXPIRES   
随后请求第五次,    Cache-status HIT
90s过后请求第六次, Cache-status MISS
第二次测试

配置

  • Cache-Control: s-maxage=60

  • Expires: 0

  • proxy_cache_valid 30s

  • inactive=10s

请求过程:

请求第一次,        Cache-status MISS        
立即请求第二次,    Cache-status HIT     
10s过后请求第三次, Cache-status MISS    
30s过后请求第三次, Cache-status MISS        
60s过后请求第四次, Cache-status MISS    
第三次测试

配置

  • Cache-Control: s-maxage=30

  • Expires: 0

  • proxy_cache_valid 50s

  • inactive=3600s

请求过程:

请求第一次,        Cache-status MISS        
立即请求第二次,    Cache-status HIT     
30s过后请求第三次, Cache-status EXPIRES    
50s过后请求第三次, Cache-status HIT        
65s过后请求第四次, Cache-status EXPIRES    
第四次测试

配置

  • Cache-Control: s-maxage=60

  • Expires: Wed, 24 Nov 2017 15:22:50 GMT # 请求时间的后30s,请求头是否在s-maxage前面都一样

  • proxy_cache_valid 10s

  • inactive=3600s

请求过程:

请求第一次,        Cache-status MISS        
立即请求第二次,    Cache-status HIT     
10s过后请求第三次, Cache-status HIT    
30s过后请求第三次, Cache-status HIT        
60s过后请求第四次, Cache-status EXPIRES    
第五次测试

配置

  • Expires: 0 #这个过期的头部设置在s-maxage前面

  • Cache-Control: s-maxage=60

  • proxy_cache_valid 10s

  • inactive=3600s

请求过程:

请求第一次,        Cache-status MISS        
立即请求第二次,    Cache-status MISS     
10s过后请求第三次, Cache-status MISS    
30s过后请求第三次, Cache-status MISS       
60s过后请求第四次, Cache-status MISS    

小结

  • Nginx的inactive设置,是指在设定的时间内,完全没有请求的缓存才会被删除,被删除之后缓存的状态就变成MISS。假设设定的时间内有请求,则从这个请求过后重新计算inactive的时间。

  • RFC 7234说明:HTTP 1.1中如果一个设置了max-age或者s-max-age指令的Cache-Control响应头,那么Expires头就会被忽略。但是实测下来发现,当php设置了EXPIRESs-max-age,假如EXPIRES是未过期时间,那它在s-max-age的前面或者后面,都会被忽略。假如EXPIRES是过期时间,它在s-max-age的前面会导致请求无法缓存,它在s-max-age的后面则会被忽略

  • proxy_cache_valids-max-age同时存在,s-max-age不受proxy_cache_valid的影响,无论是用户还是缓存服务器,都取s-max-age的值

小记: 本次测试仅供参考,诸如php的设置,或者在缓存节点再加上的头部的情况不再这次讨论范围。但总得来说,源站建议用s-max-age或者max-age来设置头部会减少比较多问题的发生。


参考文献
1、 RFC 7234
2、 http://nginx.org/en/docs/http/ngx_http_proxy_module.html

发表新评论