Nginx缓存原理及配置(页面缓存)

1.Nginx的缓存简介
nginx的http_proxy模块,可以实现类似于Squid的缓存功能。Nginx对客户已经访问过的内容在Nginx服务器本地建立副本,这样在一段时间内再次访问该数据,就不需要通过Nginx服务器再次向后端服务器发出请求,所以能够减少Nginx服务器与后端服务器之间的网络流量,减轻网络拥塞,同时还能减小数据传输延迟,提高用户访问速度。同时,当后端服务器宕机时,Nginx服务器上的副本资源还能够回应相关的用户请求,这样能够提高后端服务器的鲁棒性。

image.png

2.nginx cache的最基本的配置
nginx.conf

fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;//忽略header设置这些值的内容
fastcgi_temp_path  /tmp/nginx/fcgi/temp;

vhost配置

server {
    server_name example.com www.example.com;
 
    access_log   /var/log/nginx/example.com.access.log;
    error_log    /var/log/nginx/example.com.error.log;
 
    root /var/www/example.com/htdocs;
    index index.php;
 
    set $skip_cache 0;
 
    # POST requests and urls with a query string should always go to PHP
    if ($request_method = POST) {
        set $skip_cache 1;
    }  
    if ($query_string != "") {
        set $skip_cache 1;
    }  
 
    # Don't cache uris containing the following segments
    if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }  
 
    # Don't use the cache for logged in users or recent commenters
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }
 
    location / {
        try_files $uri $uri/ /index.php?$args;
    }   
 
    location ~ \.php($|/) {
        try_files $uri =404;
        include fastcgi_params;
        fastcgi_split_path_info         ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO         $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
        fastcgi_pass unix:/dev/shm/php-socket;
 
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
 
        fastcgi_cache WORDPRESS;
        include fcgi_cache_params;
     }
 
    location ~ /purge(/.*) {
        fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";

#这里cache_key可能有多种设定:

#商品详情页的cache的key:self.busMethod .. '-' .. productId .. '-' .. #apiVersion
#商品列表页面的cache key:self.busMethod .. '-' .. shopId .. '-' .. listType .. '-' .. cId .. '-' .. sort .. '-' .. page .. '-' .. pageSize
#店铺商品列表接口cache key:self.busMethod .. '-' .. shopId
#商品评论的列表接口 cache key:self.busMethod .. '-' .. productId .. '-' .. rateType .. '-' .. version .. '-' .. page .. '-' .. pageSize
#推广领券页接口 cache key;self.busMethod .. '-' .. couponId .. '-' .. productId
    
    #cache purge
    #$1是cache_zone $2是cache_key
    location ~ /purge/(.*)/(.*) {
        #allow 127.0.0.1;
        #allow 10.40.0.0/16;
        #deny all;
        fastcgi_cache_purge $1 $2;
    }

    }  
 
    location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        access_log off; log_not_found off; expires max;
    }
 
    location = /robots.txt { access_log off; log_not_found off; }
    location ~ /\. { deny  all; access_log off; log_not_found off; }
}

fcgi_cache_params配置

#include fcgi_cache_params;
#fastcgi_cache_valid 200 302 1s;
### fcgi-cache
fastcgi_cache fcgi;
fastcgi_cache_valid 200 302 1s;
fastcgi_cache_valid 404 500 502 503 504 0s;
fastcgi_cache_valid any 1m;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header http_500 http_503 updating;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
#add_header X-Cache "$upstream_cache_status - $upstream_response_time";
fastcgi_cache_key "$scheme$request_method$host$request_uri"

大概解释下各个参数的含义:

fastcgi_cache 该指令用于设置哪个缓存区将被使用,zone_name的值为fastcgi_cache_path指令创建的缓存名称

fastcgi_cache_path 作用域:http

fastcgi_cache_path path
[levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time]
[max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time]
[purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

该指令用于设置缓存文件的存放路径,示例如下:fastcgi_cache_path /data/nginx/cache levels=1:2 keys_zone=cache_one:100M inactive=1d max_size=10g;

a、levels:指定了该缓存空间有两层hash目录,设置缓存目录层数,levels=1:2,表示创建两层目录缓存,最多创建三层。第一层目录名取fastcgi_cache_key md5的最后一个字符,第二层目录名取倒数2-3字符,如:fastcgi_cache_key md5为b7f54b2df7773722d382f4809d65029c,则:
levels=1:2为/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c
levels=1:2:3为/data/nginx/cache/c/29/650/b7f54b2df7773722d382f4809d65029c
b、keys_zone为这个缓存区起名为zone_name,500m指代缓存空间为500MB;
c、inactive=1d 代表如果缓存文件一天内没有被访问,则删除;
d、max_size=30g代表硬盘缓存最大为30G;

设置缓存多个磁盘

fastcgi_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g  inactive=60m use_temp_path=off;
fastcgi_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g  inactive=60m use_temp_path=off;
 
split_clients $request_uri $my_cache {
              50%          "my_cache_hdd1";
              50%          "my_cache_hdd2";
}
 
server {
    ...
    location / {
       fastcgi_cache $my_cache;
    }
}

将缓存文件放入内存中
编辑/etc/fstab 或者 放入 /dev/shm

tmpfs /etc/nginx/cache tmpfs defaults,size=100M 0 0
mount -a
df -ah | grep tmpfs 

需要注意的是fastcgi_cache缓存是先写在fastcgi_temp_path再移到fastcgi_cache_path,所以这两个目录最好在同一个分区,从0.8.9之后可以在不同的分区,不过还是建议放同一分区.

fastcgi_cache_methods 该指令用于设置缓存哪些HTTP方法,默认缓存HTTP GET/HEAD方法。

fastcgi_cache_min_uses URL经过多少次请求将被缓存

fastcgi_cache_valid reply_code [reply_code ... ] time
为不同的HTTP返回状态码的资源设置不同的缓存时长。
该指令用于对不同返回状态码的URL设置不同的缓存时间,例如:

proxy_cache_valid 200 302 10m;    #为响应码是200和302的资源,设置缓存时长为10分钟
proxy_cache_valid 404      1m;    #为响应码是404的资源,设置的缓存的时长为1分钟

注意:如果不指定状态码,直接指定缓存时间,则只有200,301,302状态码会进行缓存。fastcgi_cache_valid 5m;

any 可以指定缓存任何响应码    
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;

缓存的参数也可以在响应头直接设置。这些的优先级高于缓存时间设定使用该指令.
Nginx fastcgi_cache在缓存后端fastcgi响应时,当响应里包含“set-cookie”时,不缓存;
当响应头包含Expires时,如果过期时间大于当前服务器时间,则nginx_cache会缓存该响应,否则,则不缓存;
当响应头包含Cache-Control时,如果Cache-Control参数值为no-cache、no-store、private中任意一个时,则不缓存,如果Cache-Control参数值为max-age时,会被缓存,且nginx设置的cache的过期时间,就是系统当前时间 + mag-age的值。

header("Expires: ".gmdate("D, d M Y H:i:s", time()+10000).' GMT');
header("Expires: ".gmdate("D, d M Y H:i:s", time()-99999).' GMT');
header("X-Accel-Expires:5"); // 5s
header("Cache-Control: no-cache"); //no cache
header("Cache-Control: no-store"); //no cache
header("Cache-Control: private"); //no cache
header("Cache-Control: max-age=10"); //cache 10s
setcookie('hello',"testaaaa"); //no cache

注意session使用的时候有坑,可以用下面来设置

session_cache_limiter("none");
session_start();
echo date("Y-m-d H:i:s",time());

fastcgi_cache_key该指令用来设置Web缓存的Key值,Nginx根据Key值MD5缓存。一般根据host(域名),request_uri(请求的路径)等变量组合成fastcgi_cache_key。

例如:fastcgi_cache_key "schemerequest_methodhostrequest_uri";

定义fastcgi_cache的key,示例中就以请求的URI作为缓存的key,Nginx会取这个key的md5作为缓存文件,如果设置了缓存哈希目录,Nginx会从后往前取相应的位数做为目录。

注意一定要加上$request_method作为cache key,否则如果HEAD类型的先请求会导致后面的GET请求返回为空

fastcgi_temp_path path [level1 [level2 [level3]]]; 默认为 fastcgi_temp;
该指令用来设置fastcgi_cache临时文件目录

fastcgi_temp_path /spool/nginx/fastcgi_temp 1 2;
a temporary file might look like this:
/spool/nginx/fastcgi_temp/7/45/00000123457

proxy_cache_use_stale增强站点容错能力,源站有问题时,nginx可以通过proxy_cache_use_stale指令开启容错能力,即使用缓存内容来响应客户端的请求。举个栗子:

location / {
    ...
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}

如上配置表示,当作为cache的NGINX收到源站返回error、timeout或者其他指定的5XX错误,并且在其缓存中有请求文件的陈旧版本,则会将这些陈旧版本的文件而不是错误信息发送给客户端。

x-cache头,用于调试
$upstream_response_time为过期时间

缓存命中情况的Nginx变量$upstream_cache_status,表示此请求响应来自cache的状态,几种状态分别为:
MISS —— 响应在缓存中找不到,所以需要在服务器中取得。这个响应之后可能会被缓存起来
BYPASS —— 响应来自原始服务器而不是缓存,因为请求匹配了一个proxy_cache_bypass,这个响应之后可能会被缓存起来
EXPIRED —— 缓存中的某一项过期了,来自原始服务器的响应包含最新的内容
STALE —— 内容陈旧是因为原始服务器不能正确响应。需要配置proxy_cache_use_stale
UPDATING —— 内容过期了,因为相对于之前的请求,响应的入口(entry)已经更新,并且proxy_cache_use_stale的updating已被设置
REVALIDATED —— proxy_cache_revalidate命令被启用,NGINX检测得知当前的缓存内容依然有效(If-Modified-Since或者If-None-Match)
HIT —— 响应包含来自缓存的最新有效的内容

http响应头Cache-Control,当在响应头部中Cache-Control被配置为Private,No-Cache,No-Store或者Set-Cookie,不允许代理对资源进行缓存。

3.清除缓存
NGINX只在商业版中支持proxy_cache_purge指令清除缓存,开源的ngx_cache_purge模块只支持单一key的缓存清除。为了实现按目录清除缓存只能自己开发。

NGINX作为Cache服务器时将资源内容以文件形式进行缓存,缓存元信息存储于共享内存中,组织成一棵红黑树。红黑树中的每个节点代表一个Cache元信息。NGINX将Cache Key的HASH值作为红黑树节点的KEY。内容缓存文件以该HASH值作为文件名存储在磁盘上。

NGINX的处理流程简化描述是这样的:当请求到达时,根据Cache Key的HASH值在红黑树中进行查找。如果找到,并查看相关信息,如果Cache可用,返回相应的Cache文件。否则,则回源抓取。

因为元信息是以Cache Key的HASH值作为Key存储的,因而红黑树中并不能保留Cache Key中有层级关系. 如”/uri/foo”和”/uri/bar”在元信息红黑树中完全没有关系。要实现按照目录清除缓存,需要将Cache Key中层次关系存储起来。

可以这样做,在共享内存中建立一棵目录树来存储层级关系。将Cache Key类比于文件系统中的路径, 每级路径存储为树中的一个节点。当需要清除某一目录下的所有缓存时,将该节点子树的中的所有缓存清除即可。

安装Purge模块
Purge模块被用来清除缓存:

wget http://labs.frickle.com/files/ngx_cache_purge-1.2.tar.gz
tar -zxvf ngx_cache_purge-1.2.tar.gz

编译

./configure \
…… \
--with-http_geoip_module \
--add-module=/usr/local/ngx_cache_purge-1.2
  1. 需要注意的一些问题
    设置了之后重启nginx就可以生效了,这个时候再访问php的页面的话,就会被缓存了,可以查看/var/logs/nginx/fastcgi_cache_dir这个目录下面是有缓存文件的。最后再说明一点,如果更改了缓存目录的路径,一定要把缓存的名称也改掉,后端调用的名称也同步改掉,如果只改掉了缓存目录,不改缓存名称的话,缓存的时候还是会缓存到之前的路径下面去,但是调用的时候调用的是新的路径,这个时候就会出现找不到的情况
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容