用Nginx fastcgi_cache缓存为你的PHP网站加速

Nginx + PHP7-FPM + FastCGI (+ProcessWire) = Fast!

的后续,该项目今天正式部署,由于对Nginx的知识缺乏导致之前有一些错误的认知:

本来以为用ProcessWire输出成"text/css"和"application/javascript"这类前端静态文件会被Nginx自动缓存,殊不知Nginx默认缓存的物理文件,而由PHP输出成的文件需要特别用fastcgi_cache来处理。

静态文件的处理方法,在《》一文记录过:

	location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|eot|otf|woff|woff2|ttc|ttf)$ {
        add_header Access-Control-Allow-Origin *;
		expires 1y;
		log_not_found off;
		access_log off;
		try_files $uri $uri/ /index.php?it=$uri&$args;
	}

注意:这里缓存的是物理文件。

用Nginx缓存PHP文件的方法

缓存位置的基础配置

找到站点配置.conf文件,在server{}配置上面加上:

fastcgi_cache_path /path/to/nginx/cache levels=1:2 keys_zone=microcache:10m max_size=1024m inactive=1h;
add_header X-Cache $upstream_cache_status;

需要修改的参数:/path/to/nginx/cache 是缓存文件的存放目录;keys_zone=microcache就是当前的应用名称,这里的microcache后面还会用到。

注意:$upstream_cache_status参数的几个值,后面测试查看X-Cache的状态都依赖于该参数:

  • MISS 未命中,请求被传送到后端
  • HIT 缓存命中
  • EXPIRED 缓存已经过期请求被传送到后端
  • UPDATING 正在更新缓存,将使用旧的应答
  • STALE 后端将得到过期的应答

缓存触发条件的设定

server{}中加入以下配置:

	#缓存全部
	set $no_cache 0;

	#仅限于GET请求,其它请求禁止缓存
	if ($request_method != GET){
	    set $no_cache 1;
	}

	#URL中带有Query参数的时候禁止缓存,应为ProcessWire由index.php文件作为入口,所以我这里用不到
	#if ($query_string != ""){
	#    set $no_cache 1;
	#}

	#URL中出现这些目录的时候禁止缓存
	if ($request_uri ~* "/(admin|backendpath)"){
	    set $no_cache 1;
	}

	#如果cookie中有PHPSESSID的变量的时候禁止缓存
	if ($http_cookie ~* "PHPSESSID"){
	    set $no_cache 1;
	}

	#如果cookie中有wire_challenge的时候不要缓存,该参数在用户登录后出现
	if ($http_cookie ~* "wire_challenge"){
	    set $no_cache 1;
	}		

让缓存工作

location ~ \.php$ {}中加入以下配置:

		#Set cache

	    fastcgi_cache_key $scheme$host$request_uri$request_method;
	    fastcgi_cache  microcache;
	    fastcgi_cache_valid 200 301 302 30s;
	    fastcgi_cache_use_stale updating error timeout invalid_header http_500;

	    fastcgi_pass_header Set-Cookie;
	    fastcgi_pass_header Cookie;
	    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

	    fastcgi_cache_bypass $no_cache;
	    fastcgi_no_cache $no_cache;

		#Set cache end
		

缓存的测试方法

curl -X GET -I http://yourwebsite.com
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Mon, 27 Feb 2017 14:05:06 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: wire=4150jee3917k8e2dv4ioka1sq6; path=/; HttpOnly
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
X-Powered-By: ProcessWire CMS
X-Cache: HIT

注意X-Cache参数,如果是HIT就是已经缓存了的,因为缓存机制是访问后被缓存,所以如果你是第一次访问可能这里的值是MISS.

同样你还可以通过Chrome F12开发者模式查看页面或文件的Headers信息查看X-Cache状态,下面是访问触发禁止缓存的页面或用户登录后的状态:

Response Headers

Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Type:application/javascript
Date:Mon, 27 Feb 2017 14:08:25 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx/1.10.1
Transfer-Encoding:chunked
X-Cache:BYPASS
X-Powered-By:ProcessWire CMS

注意:这里的X-Cache:BYPASS,即为非缓存内容.

Post Comment