转自
先说一下我对缓存的理解:缓存可以让用户更加接近数据。HTTP缓存指我们用浏览器访问网站时,根据服务器返回的HTTP缓存响应头设置,缓存相应的数据,下次访问就可以直接使用,或者去服务器验证数据是否过期。这样可以大大减轻宽带压力,加快网页加载速度。
当我们首次访问http://www.2cto.com/uploadfile/2016/1008/20161008090645827.jpg 时,得到如下响应头:
服务器返回如下几个缓存控制头部:
nginx在生成etag时使用的算法是Last-Modified + Content-Length计算的。根据规范定义Cache-Control优先级高于Expires,实际使用时可以两个都用,或仅使用Cache-Control就可以了。一般情况下Expires=当前系统时间(Date) + 缓存时间(Cache-Control: max-age)。
当我们再次访问http://www.2cto.com/uploadfile/2016/1008/20161008090645827.jpg 时,发现浏览器请求头部有变化:
Modified-Since请求头,其值是上次请求响应中的Last-Modified,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
If-None-Match请求头,其值是上次请求响应中的ETag,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
Last-Modified与ETag同时使用时,浏览器在验证时会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,如果同时使用If-Modified-Since和If-None-Match则服务端必须两个都验证通过后才能返回304;且nginx就是这样做的。因此实际使用时应该根据实际情况选择。
浏览器在请求时不会带上If-Modified-Since,并带上Cache-Control:no-cache和Pragma:no-cache,这是为了告诉服务端说我请给我一份最新的内容。
304表示服务器返回文档没有过期
200 (from cache) 表示浏览器直接使用缓存数据
Last-Modified/Modified-Since 用于验证文档内容是否变更 max-age/Expires 定义文档缓存时间,如在有效期内会返回 200(from cache)
expires:控制Expires响应头
etag (off):控制是否返回Etag响应头
if-modified-since (before/exact): exact表示精确匹配,before表示文件修改时间早于浏览器If-Modified-Since时间,就返回304
nginx作为反向代理,所有请求都会先请求至nginx,再由nginx转发
如果使用Expires可以修改返回浏览器Expires头部信息,但是nginx只负责转发请求和负载均衡,没有为后端服务器分担压力。
这是我们需要nginx在本地对访问内容进行缓存,如果文件还在缓存期内,由nginx返回304响应,否则再转发至后台,并且nginx再次更新自己的本地缓存。
proxy_cache :指定使用哪个共享内存区域存储缓存键和相关信息;
proxy_cache_key :设置缓存使用的key,默认为访问的完整URL,根据实际情况设置缓存key;
proxy_cache_valid :为不同的响应状态码设置缓存时间;如果是proxy_cache_valid 5s 则200、301、302响应将被缓存;
proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下):
以秒为单位的“X-Accel-Expires”响应头来设置响应缓存时间 如果没有“X-Accel-Expires”,可以根据“Cache-Control”、“Expires”来设置响应缓存时间 否则使用proxy_cache_valid设置的缓存时间
如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。
当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off)则只有一个请求被发送至后端;其他请求将等待该内容返回;当第一个请求返回时,其他请求将从缓存中获取内容返回;当第一个请求超过了proxy_cache_lock_timeout超时时间(默认5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存;启用proxy_cache_lock可以应对雪崩效应。
有时候缓存的内容是错误的,需要手工清理,可以使用ngx_cache_purge模块进行清理缓存,如:
这样只允许本地可以访问,另外也可以配置password访问
缓存虽然不是什么很高深的的技术,但是缓存是抗流量冲击的银弹,起到的作用举足轻重 静态文件是可以缓存很久的 缓存是可以预热的 如果业务场景允许,可以做开关,在遭受到流量冲击的时候全部走缓存,不回流到后端服务器 只缓存200的响应, 后端响应错误不要返回200 缓存的key设置需要合理,可以做个工具,快速删除不正确的缓存