Nginx版本从0.7.48开始,支持了相似Squid的缓存功能。这个缓存是把URL及相关组合当作Key,用Md5算法对Key进行哈希,获得硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录内。php
Nginx Web 缓存服务只能为指定URL或状态码设置过时时间,不支持相似Squid的PURGE指令手动清除缓存;可是咱们能够经过Nginx的模块ngx_cache_purge清除指定URL的缓存。html
图片来自网络mysql
nginx.confnginx
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; 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"; } 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配置sql
#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
该指令用于对不一样返回状态码的URL设置不一样的缓存时间,例如:
fastcgi_cache_valid 200 302 10m; fastcgi_cache_valid 404 1m;
设置202 302状态URL缓存10分钟,404状态的URL缓存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;
缓存的参数也能够在响应头直接设置。这些的优先级高于缓存时间设定使用该指令
@
prefix, it sets an absolute time in seconds since Epoch, up to which the response may be cached.*
”, such a response will not be cached (1.7.7). If the header includes the “Vary” field with another value, such a response will be cached taking into account the corresponding request header fields (1.7.7).fastcgi_cache_key
该指令用来设置Web缓存的Key值,Nginx根据Key值MD5缓存。通常根据$host(域名),$request_uri(请求的路径)等变量组合成fastcgi_cache_key。
例如:fastcgi_cache_key "$scheme$request_method$host$request_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
fastcgi_cache_use_stale : fastcgi_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_503 | http_403 | http_404 | off ...;
定义哪些状况下用过时缓存
$upstream_response_time为过时时间
$upstream_cache_status 变量表示此请求响应来自cache的状态,几种状态分别为:
有一些状况会影响到cache的命中 这里须要特别注意
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());
//ext/session/session.c line:1190 左右 // ... CACHE_LIMITER_FUNC(private) /* {{{ */ { ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); CACHE_LIMITER(private_no_expire)(TSRMLS_C); } /* }}} */ //再到这里3 或者上面几个 ##默认是nocache CACHE_LIMITER_FUNC(nocache) /* {{{ */ { ADD_HEADER("Expires: Thu, 19 Nov 1981 08:52:00 GMT"); /* For HTTP/1.1 conforming clients and the rest (MSIE 5) */ ADD_HEADER("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); /* For HTTP/1.0 conforming clients */ ADD_HEADER("Pragma: no-cache"); } /* }}} */ //这里2 static php_session_cache_limiter_t php_session_cache_limiters[] = { CACHE_LIMITER_ENTRY(public) CACHE_LIMITER_ENTRY(private) CACHE_LIMITER_ENTRY(private_no_expire) CACHE_LIMITER_ENTRY(nocache) {0} }; static int php_session_cache_limiter(TSRMLS_D) /* {{{ */ { php_session_cache_limiter_t *lim; if (PS(cache_limiter)[0] == '\0') return 0; if (SG(headers_sent)) { const char *output_start_filename = php_output_get_start_filename(TSRMLS_C); int output_start_lineno = php_output_get_start_lineno(TSRMLS_C); if (output_start_filename) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot send session cache limiter - headers already sent"); } return -2; } for (lim = php_session_cache_limiters; lim->name; lim++) { if (!strcasecmp(lim->name, PS(cache_limiter))) { lim->func(TSRMLS_C); //这里1 return 0; } } return -1; }
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模块被用来清除缓存
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
设置了以后重启nginx就能够生效了,这个时候再访问php的页面的话,就会被缓存了,能够查看/var/logs/nginx/fastcgi_cache_dir这个目录下面是有缓存文件的。最后再说明一点,若是更改了缓存目录的路径,必定要把缓存的名称也改掉,后端调用的名称也同步改掉,若是只改掉了缓存目录,不改缓存名称的话,缓存的时候仍是会缓存到以前的路径下面去,可是调用的时候调用的是新的路径,这个时候就会出现找不到的状况
参考文章
http://www.nginxtips.com/configure-nginx-fastcgi-cache/
http://www.haidx.com/fastcgi-cache-details.html
http://www.just4coding.com/blog/2014/11/01/nginx-purge-directory/
http://weizhifeng.net/nginx-proxy-cache.html
https://www.nginx.com/blog/nginx-caching-guide/#gs.6PdbraI
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache
https://www.cnxct.com/several-reminder-in-nginx-fastcgi_cache-and-php-session_cache_limiter/
https://rtcamp.com/wordpress-nginx/tutorials/single-site/fastcgi-cache-with-purging/
http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache