Nginx提供了expires、etag、if-modified-since指令来实现浏览器缓存控制。
一、expires
如果我们使用Nginx作为静态资源服务器,那么可以使用expires进行缓存控制。
- location /img {
- alias /export/img/;
- expires 1d;
- }
当我们访问静态资源时,如http://192.168.61.129/img/1.jpg,将得到类似如下的响应头。
对于静态资源会自动添加ETag,可以通过添加etag off指令禁止生成ETag。如果是静态文件,那么Last-Modified值为文件的***修改时间。Expires是根据当前服务器系统时间算出来的。如上Nginx配置的计算逻辑(实际计算逻辑比这个多,具体参考官方文档)。
- if (expires == NGX_HTTP_EXPIRES_ACCESS||r->headers_out.last_modified_ time == -1) {
- max_age = expires_time;
- expires_time += now;
- }
二、if-modified-since
此指令用于指定Nginx如何拿服务端的Last-Modified和浏览器端的if-modified- since时间进行比较,默认“if_modified_since exact”表示精确匹配,也可以使用“if_modified_since _before”表示只要文件的***修改时间早于或等于浏览器端的if-modified-since时间,就返回304。
三、nginx proxy_pass
使用Nginx作为反向代理时,请求会先进入Nginx,然后Nginx将请求转发给后端应用,如下图所示。
首先配置upstream。
- upstream backend_tomcat {
- server 192.168.61.1:9080max_fails=10 fail_timeout=10s weight=5;
- }
接着配置location。
- location = /cache {
- proxy_pass http://backend_tomcat/cache$is_args$args;
- }
接下来,我们可以通过如http://192.168.61.129/cache?millis=1471349916709访问Nginx,Nginx会将请求转发给后端Java应用。也就是说Nginx只是做了相关的转发(负载均衡),并没有对请求和响应做什么处理。
假设对后端返回的过期时间需要调整,可以添加Expires指令到location。
- location = /cache {
- proxy_pass http://backend_tomcat/cache$is_args$args;
- expires 5s;
- }
然后再请求相关的URL,将得到如下响应。
过期时间相关的响应头被Expires指令更改了,但是last-modified是没有变的。
即使我们更改了缓存过期头,但Nginx自己没有对这些内容做代理层缓存,每次请求还是要到后端验证的,假设在过期时间内,这些验证在Nginx这一层验证就可以了,不需要到后端验证,这样可以减少后端很大的压力。即整体流程如下。
1.浏览器发起请求,首先到Nginx,Nginx根据URL在Nginx本地查找是否有代理层本地缓存。
2.Nginx没有找到本地缓存,则访问后端获取***的文档,并放入到Nginx本地缓存中,返回200状态码和***的文档给浏览器。
3.Nginx找到本地缓存,首先验证文档是否过期(Cache-Control:max-age=5),如果过期,则访问后端获取***的文档,并放入Nginx本地缓存中,返回200状态码和***的文档给浏览器;如果文档没有过期,即if-modified-since与缓存文档的last-modified匹配,则返回304状态码给浏览器。
内容不需要访问后端,即不需要后端动态计算/渲染等,直接Nginx代理层就把内容返回了,速度更快,内容越接近于用户速度越快。像ApacheTraffic Server、Squid、Varnish、Nginx等技术都可以用来进行内容缓存。还有CDN技术就是用来加速用户访问的。
即用户首先访问到全国各地的CDN节点(使用如ATS、Squid实现),如果CDN没***,则会回源到中央Nginx集群,该集群做二级缓存,如果没有***缓存(该集群的缓存不是必须的,要根据实际***情况等决定),则***回源到后端应用集群。
像我们商品详情页的一些服务就大量使用了Nginx缓存减少回源到后端的请求量,从而提升访问速度。可以参考 “ 构建需求响应式亿级商品详情页”和“ 京东商品详情页服务闭环实践”。
四、Nginx代理层缓存
1. Nginx代理层缓存配置
HTTP模块配置
- proxy_buffering on;
- proxy_buffer_size 4k;
- proxy_buffers 5124k;
- proxy_busy_buffers_size 64k;
- proxy_cache_path /export/cache/proxy_cachelevels=1:2 keys_zone=cache:512m inactive=5m max_size=8g use_temp_path=off;
- #proxy timeout
- proxy_connect_timeout 3s;
- proxy_read_timeout 5s;
- proxy_send_timeout 5s;
proxy_cache_path指令配置:
2. location配置
- location = /cache {
- proxy_cache cache;
- proxy_cache_key$scheme$proxy_host$request_uri;
- proxy_cache_valid 200 5s;
- proxy_passhttp://backend_tomcat/cache$is_args$args;
- add_header cache-status$upstream_cache_status;
- }
3. 缓存相关配置
4. proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下)。
如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。
add_header cache-status $upstream_cache_status在响应头中添加缓存***的状态。
5. proxy_cache_min_uses
用于控制请求多少次后响应才被缓存。默认“proxy_cache_min_uses1;”,如果缓存热点比较集中、存储有限,则可以通过修改该参数来来减少缓存数量和写磁盘次数。
6. proxy_no_cache
用于控制什么情况下响应不被缓存。比如配置“proxy_no_cache$args_nocache”,如果带的nocache参数值至少有一个不为空或者为0,则响应将不被缓存。
7. proxy_cache_bypass
类似于proxy_no_cache,但是,其控制什么情况不使用缓存的内容,而是直接到后端获取***的内容。如果***,则$upstream_cache_status为BYPASS。
8. proxy_cache_use_stale
当对缓存内容的过期时间不敏感,或者后端服务出问题时,即使缓存的内容不新鲜也总比返回错误给用户强(类似于托底),此时可以配置该参数,如“proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504”,即如果出现超时、后端连接出错、500、502、503等错误时,则即使缓存内容已过期也先返回给用户,此时$upstream_cache_status为STALE。还有一个updating表示缓存已过期但正在被别的Nginx Worker进程更新,但先返回了过期内容,此时$upstream_cache_status为UPDATING。
9. proxy_cache_revalidate
当缓存过期后,如果开启了proxy_cache_revalidate,则会发出一次if-modified-since或if-none-match条件请求,如果后端返回304,则此时$upstream_cache_status为REVALIDATED,我们将得到两个好处,节省带宽和减少写磁盘的次数。
10. proxy_cache_lock
当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off),则只有一个请求被发送至后端。其他请求将等待该请求的返回。当***个请求返回后,其他相同请求将从缓存中获取内容返回。当***个请求超过了proxy_cache_lock_timeout超时时间(默认为5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的)。启用proxy_cache_lock可以应对Dog-pile effect(当某个缓存失效时,同时有大量相同的请求没***缓存,而同时请求到后端,从而导致后端压力太大,此时限制一个请求去拿即可)。
proxy_cache_lock_age是1.7.8新添加的,如果在proxy_cache_lock_age指定的时间内(默认为5s),***一个发送到后端进行新缓存构建的请求还没有完成,则下一个请求将被发送到后端来构建缓存(因为1.7.8版本之后,proxy_cache_lock_timeout超时之后返回的内容是不缓存的,需要下一次请求来构建响应缓存)。
五、清理缓存
有时缓存的内容是错误的,需要手工清理,Nginx企业版提供了purger功能,对于社区版Nginx可以考虑使用ngx_cache_purge(https://github.com/FRiCKLE/ngx_cache_purge)模块进行清理缓存。
- location ~ /purge(/.*) {
- allow 127.0.0.1;
- deny all;
- proxy_cache_purge cache$1$is_args$args;
- }
该方法要限制其访问权限,如只允许内网可以访问或者需要密码才能访问。
到此代理层缓存就介绍完了,通过代理层缓存可以解决很多问题,可以参考“京东商品详情页服务闭环实践”。
【本文是专栏作者张开涛的原创文章,作者微信公众号:开涛的博客( kaitao-1234567)】
当前文章:张开涛:NginxHTTP缓存设置
本文URL:http://www.shufengxianlan.com/qtweb/news45/362895.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联