Nginx+FastCGI 运行 WordPress 和 WP Super Cache

wordpress

有了一个自己的 VPS 主机以后就自由多了,拥有 root 访问权限,几乎可以做任何事情,VPS 一开通我就迫不及待的想要用 nginx 换掉笨重的 apache,share hosting 就没那么幸运了,只能给什么用什么了。

WP Super Cache 是一个 WordPress 插件,用来给 WordPress 提供缓存,也就是说用户请求一个 WordPress PHP 页面后,WP Super Cache 会把结果转化成 HTML 文件保存下来,这样下次用户访问同一个页面的时候就会优先访问那个已保存的 HTML 文件,这样中间就没有 PHP 解析的过程,所以速度非常快,是高流量博客的必备插件。

说明一下为什么需要 FastCGI?Nginx 体积很小,本身不带 CGI 模块,所以需要和第三方配合以支持各种动态脚本的解析。这些解析脚本是如何和 web server 交流的呢?这时需要一个叫做 FastCGI 的支持。那么什么是 FastCGI 呢?FastCGI 是一个外部程序和 web server 之间打交道的协议/接口,有点像应用程序 API 和操作系统之间的关系。与老的 CGI 比起来,FastCGI 可以同时启动多个进程,而 CGI 程序只能运行在一个进程里,这意味着 FastCGI 的性能比 CGI 好得多;FastCGI 的运行完全和 web server 独立,就是说即使 FastCGI down 掉了也不会影响到 web server。

目前较普遍的有两种方法支持 FastCGI,一种是用 lighttpd 的 spawn-fcgi 程序;另外一种是直接用内嵌在 PHP 里面的 php-cgi。这里以第一种方法(spawn-fcgi)为例。

CentOS 上安装 nginx+spawn-fcgi

安装 nginx 和 spawn-fcgi

# rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/
epel-release-5-3.noarch.rpm

# yum install nginx
# yum install spawn-fcgi


创建一个文件 /etc/init.d/php_cgi 并保存以下内容作为 CentOS 上 FastCGI 的启动配置文件。

#!/bin/sh
#
# php-cgi - php-fastcgi swaping via spawn-fcgi
#
# chkconfig:   - 85 15
# description:  Run php-cgi as app server
# processname: php-cgi
# config:      /etc/sysconfig/phpfastcgi (defaults RH style)
# pidfile:     /var/run/php_cgi.pid
# Note: See how to use this script :
# http://www.cyberciti.biz/faq/rhel-fedora-install-configure-nginx-php5/
# Source function library.
. /etc/rc.d/init.d/functions
 
# Source networking configuration.
. /etc/sysconfig/network
 
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
 
spawnfcgi="/usr/bin/spawn-fcgi"
php_cgi="/usr/bin/php-cgi"
prog=$(basename $php_cgi)
server_ip=127.0.0.1
server_port=9000
server_user=nginx
server_group=nginx
server_childs=5
pidfile="/var/run/php_cgi.pid"
 
# do not edit, put changes in /etc/sysconfig/phpfastcgi
[ -f /etc/sysconfig/phpfastcgi ] && . /etc/sysconfig/phpfastcgi
 
start() {
    [ -x $php_cgi ] || exit 1
    [ -x $spawnfcgi ] || exit 2
    echo -n $"Starting $prog: "
    daemon $spawnfcgi -a ${server_ip} -p ${server_port} -u ${server_user} -g ${server_group} -P ${pidfile} -C ${server_childs} -f ${php_cgi}
    retval=$?
    echo
    return $retval
}
 
stop() {
    echo -n $"Stopping $prog: "
    killproc -p ${pidfile} $prog -QUIT
    retval=$?
    echo
    [ -f ${pidfile} ] && /bin/rm -f ${pidfile}
    return $retval
}
 
restart(){
	stop
	sleep 2
	start
}
 
rh_status(){
	status -p ${pidfile} $prog
}
 
case "$1" in
    start)
        start;;
    stop)
        stop;;
    restart)
        restart;;
    status)
        rh_status;;
    *)
        echo $"Usage: $0 {start|stop|restart|status}"
        exit 3
esac

注意要把上面刚创建的文件变为可执行脚本:

# chmod +x /etc/init.d/php_cgi

在 Cent OS 上启动 FastCGI:

# /etc/init.d/php_cgi start

# netstat -tulpn | grep :9000

把脚本加入系统启动文件:

# /sbin/chkconfig --add php_cgi
# /sbin/chkconfig php_cgi on
# /sbin/chkconfig --list

Debian 上安装 nginx+spawn-fcgi

安装 nginx 和 spawn-fcgi(注意 spawn-fcgi 在 lighttpd 软件包里,安装完后删除 lighttpd 只留下 spawn-fcgi)

# apt-get install nginx
# /etc/init.d/nginx start
# update-rc.d nginx defaults
# apt-get install lighttpd
# update-rc.d -f lighttpd remove

在 Debian 上启动 FastCGI

# /usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -g www-data 
-f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid

如果你不想每次系统重新启动后都打入上面一长串命令的话,建议把上面的命令加到启动文件中。

# vi /etc/rc.local

配置 Nginx

打开 /etc/nginx/sites-available/default,找到相应地方用下面的配置替换掉。(注意:如果只用WordPress 的话就把 #include /etc/nginx/wordpress_params_regular; 一行的注释拿掉;如果要用 WP Super Cache 的话就把 #include /etc/nginx/wordpress_params_supercache; 一行拿掉。)

# fix nginx/php/fastcgi important security issue
# http://cnedelcu.blogspot.com/2010/05/nginx-php-via-fastcgi-important.html
location ~ \..*/.*\.php$ {
    return 403;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
    include /etc/nginx/fastcgi_params;
    #include /etc/nginx/wordpress_params_regular;
    #include /etc/nginx/wordpress_params_supercache;
}

配置 Nginx 的参数支持 WordPress 和 WP Super Cache

让 wordpres_params_regular 配置文件和 wordpress_params_supercache 配置文件包含进来。

在 /etc/nginx/ 下创建 wordpress_params_regular 文件,把以下内容拷过去

# WordPress pretty URLs
if (-f $request_filename) {
expires max;
break;
}
if (-d $request_filename) {
break;
}
rewrite ^(.+)$ /index.php?q=$1 last;

# Enable nice permalinks for WordPress
error_page  404  = //index.php?q=$uri;

在 /etc/nginx/ 下创建 wordpress_params_supercache 文件,把以下内容拷过去

# if the requested file exists, return it immediately
if (-f $request_filename) {
expires 30d;
break;
}

set $supercache_file '';
set $supercache_uri $request_uri;

if ($request_method = POST) {
set $supercache_uri '';
}

# Using pretty permalinks, so bypass the cache for any query string
if ($query_string) {
set $supercache_uri '';
}

if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
set $supercache_uri '';
}

# if we haven't bypassed the cache, specify our supercache file
if ($supercache_uri ~ ^(.+)$) {
set $supercache_file /var/www/wp-content/cache/supercache/$http_host/$1index.html;
}

# only rewrite to the supercache file if it actually exists
if (-f $document_root$supercache_file) {
rewrite ^(.*)$ $supercache_file break;
}

# all other requests go to WordPress
if (!-e $request_filename) {
rewrite . /var/www/index.php last;
}

重新启动 Nginx

# /etc/init.d/nginx restart

评论 (4 Comments)

  1. 请问有伪静态的代码吗?

  2. 伪静态?不大明白什么意思?你是说把 wordpress 的 php 页面静态化 html 吗?wp super cache 就是干这件事的。

  3. 我在做 Nginx + WordPress + Wp Super Cache 时参考你们的配置文件,有两点疑问:
    1、我把配置文件是放在
    location / {
    root /var/www/blog;
    index index.php index.html index.htm;
    #Wordpress rewrite
    #if (!-f $request_filename){
    # rewrite (.*) /index.php;
    #}
    include wordpress_params_supercache;
    #include wordpress_params_regular;
    }
    的,如果放在location ~ \.php$ {} 中就出错。我发现你们的文章里是放在这个区块的。个人的理解,如果客户端请求如 /test/test1/ 这样的 URL 里面是不包含 php 字样的,它又怎么能被放在这个区块被处理呢?

    2、我查了一下网上其它资料,一般的写法是
    # all other requests go to WordPress
    if (!-e $request_filename) {
    rewrite . /index.php last;
    }
    而不是 rewrite . /var/www/index.php last;
    这是没有设置root /var/www; 的写法还是怎么一回事? 我设置了 root /var/www/blog; 用你们文章中的写法就出错。

    VPS 看来不错,以后有 money 了考虑一下 :-)

  4. 不知道使用wordpress_params_supercache效果怎么要,我的博客流量很小

发表评论