专栏名称: 亿级流量网站架构
开涛技术点滴
目录
相关文章推荐
OSC开源社区  ·  大模型撞上“算力墙”,超级应用的探寻之路 ·  23 小时前  
OSC开源社区  ·  谷歌安卓系统“假开源、真垄断”? ·  2 天前  
程序员的那些事  ·  Rust ... ·  昨天  
程序员的那些事  ·  趣图:“微软穷疯了?上架的 ... ·  2 天前  
OSC开源社区  ·  继V3之后,沐曦GPU再完成DeepSeek ... ·  4 天前  
51好读  ›  专栏  ›  亿级流量网站架构

Nginx HTTP缓存设置

亿级流量网站架构  · 公众号  · 程序员  · 2017-05-09 07:32

正文

相关文章

聊聊高并发系统之HTTP缓存

应用多级缓存模式支撑海量读服务

应用级缓存——《亿级流量》

应用级缓存示例

应用级缓存之缓存使用模式实践—《亿级流量》



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缓存减少回源到后端的请求量,从而提升访问速度。可以参考“第11章 多级缓存”、“第16章 构建需求响应式亿级商品详情页 ”和“第17章 京东商品详情页服务闭环实践 ”。

Nginx代理层缓存


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指令配置:

levels=1:2:表示创建两级目录结构,缓存目录的第一级目录是1个字符,第二级目录是2个字符,比如/export/cache/proxy_cache/7/3c/,如果将所有文件放在一级目录下的话,文件量很大,会导致文件访问慢。

keys_zone=cache:512m :设置存储所有缓存key和相关信息的共享内存区,1M大约能存储8000个key。

inactive=5m :inactive指定被缓存的内容多久不被访问将从缓存中移除,以保证内容的新鲜,默认为10分钟。

max_size=8g :最大缓存阀值,“cache manager”进程会监控最大缓存大小,当缓存达到该阀值时,该进程将从缓存中移除最近最少访问的内容。

use_temp_path:如果为on,则内容首先被写入临时文件(proxy_temp_path ),然后重命名到proxy_cache_path指定的目录;如果设置为off,则内容直接被写入到proxy_cache_path指定的目录,如果需要cache建议off,则该特性是1.7.10提供的。


1.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;

}


2.缓存相关配置

proxy_cache:指定使用哪个共享内存区存储缓存信息。

proxy_cache_key :设置缓存使用的key,默认为完整的访问URL,根据实际情况设置缓存key。

proxy_cache_valid :为不同的响应状态码设置缓存时间。如果是proxy_cache_valid5s,则200、301、302响应都将被缓存。

3.proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下)。

1.以秒为单位的“X-Accel-Expires”响应头来设置响应缓存时间。

2.如果没有“X-Accel-Expires”,则可以根据“Cache-Control”、“Expires”来设置响应缓存时间。

3.否则,使用proxy_cache_valid设置缓存时间。

如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。


add_header cache-status $upstream_cache_status在响应头中添加缓存命中的状态。

HIT:缓存命中,直接返回缓存中内容,不回源到后端。

MISS:缓存未命中,回源到后端获取最新的内容。

EXPIRED:缓存命中但过期了,回源到后端获取最新的内容。

UPDATING:缓存已过期但正在被别的Nginx Worker进程更新,配置了proxy_cache_use_stale updating指令时会存在该状态。

STALE:缓存已过期,但因后端服务出现了问题(比如后端服务挂了)返回过期的响应,配置了如proxy_cache_use_stale error timeout指令后会出现该状态。

REVALIDATED:启用proxy_cache_revalidate指令后,当缓存内容过期时,Nginx通过一次if-modified-since的请求头去验证缓存内容是否过期,此时会返回该状态。

BYPASS:proxy_cache_bypass指令有效时,强制回源到后端获取内容,即使已经缓存了。







请到「今天看啥」查看全文