作者:链上研发
时间:2016-09-21
先说一下我对缓存的理解:缓存可以让用户更加接近数据
HTTP缓存指我们用浏览器访问网站时,根据服务器返回的HTTP缓存响应头设置,缓存相应的数据,下次访问就可以直接使用,或者去服务器验证数据是否过期。这样可以大大减轻宽带压力,加快网页加载速度。
当我们首次访问http://sage.moe/content/images/2016/07/masuzu-desktopsky-22521-jpg-900.jpg 时,得到如下响应头:
服务器返回如下几个缓存控制头部:
根据规范定义Cache-Control优先级高于Expires,实际使用时可以两个都用,或仅使用Cache-Control就可以了。一般情况下Expires=当前系统时间(Date) + 缓存时间(Cache-Control: max-age)。
当我们再次访问http://sage.moe/content/images/2016/07/masuzu-desktopsky-22521-jpg-900.jpg 时,发现浏览器请求头部有变化:
1. Modified-Since请求头,其值是上次请求响应中的Last-Modified,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
2. If-None-Match请求头,其值是上次请求响应中的ETag,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
Last-Modified与ETag同时使用时,浏览器在验证时会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,如果同时使用If-Modified-Since和If-None-Match则服务端必须两个都验证通过后才能返回304;且nginx就是这样做的。因此实际使用时应该根据实际情况选择。
当我们按下cmd-F5强制刷新后:
浏览器在请求时不会带上If-Modified-Since,并带上Cache-Control:no-cache和Pragma:no-cache,这是为了告诉服务端说我请给我一份最新的内容。
304表示服务器返回文档没有过期
主要配置:
静态文件配置:
nginx作为反向代理,所有请求都会先请求至nginx,再由nginx转发
如果使用Expires可以修改返回浏览器Expires头部信息,但是nginx只负责转发请求和负载均衡,没有为后端服务器分担压力。
这是我们需要nginx在本地对访问内容进行缓存,如果文件还在缓存期内,由nginx返回304响应,否则再转发至后台,并且nginx再次更新自己的本地缓存。
nginx本地缓存http配置:
主要介绍下proxy_cache_path配置
nginx本地缓存location配置:
1. proxy_cache :指定使用哪个共享内存区域存储缓存键和相关信息;
2. proxy_cache_key :设置缓存使用的key,默认为访问的完整URL,根据实际情况设置缓存key;
3. proxy_cache_valid :为不同的响应状态码设置缓存时间;如果是proxy_cache_valid 5s 则200、301、302响应将被缓存;
如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。
有时候缓存的内容是错误的,需要手工清理,可以使用ngx_cache_purge模块进行清理缓存,如:
这样只允许本地可以访问,另外也可以配置password访问
今天线上缓存出了问题,发现响应头部竟然没有Cache-Control头部。关于没有Cache-Control头部的行为HTTP协议没有规定,只有建议(有可能我没看到)。找到了火狐浏览器的实现方式如下:
The freshness lifetime is calculated based on several headers. If a “Cache-control: max-age=N” header is specified, then the freshness lifetime is equal to N. If this header is not present, which is very often the case, it is checked if an Expires header is present. If an Expires header exists, then its value minus the value of the Date header determines the freshness lifetime. Finally, if neither header is present, look for a Last-Modified header. If this header is present, then the cache’s freshness lifetime is equal to the value of the Date header minus the value of the Last-modified header divided by 10.
简单来说没有Cache-Control头部,Cache-Control 默认为private, max-age=Date header 的值减去Last-modified header 值的10%