还记得Nginx刚出来不久我曾经有试用过(当时还租在瑞豪VPS的时候),但是没两天就又被我换回了Apache。毕竟Apache用惯了,配置也相对熟悉,重要的是Bug少稳定性高。但是这两天晚上在研究Nginx的时候发现淘宝也从Nginx的基础上发展出一个Tengine的Web服务器项目,官方介绍如下:

Tengine是由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网天猫商城等得到了很好的检验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。

从2011年12月开始,Tengine成为一个开源项目,Tengine团队在积极地开发和维护着它。Tengine团队的核心成员来自于淘宝搜狗等互联网企业。Tengine是社区合作的成果,我们欢迎大家参与其中,贡献自己的力量。

因此我稍微研究了一下Tengine,在另外一台配置较低的VPS上测试了一番,发现速度确实很快,最终抱着折腾的态度,今天安装起来玩玩。

目前我的VPS上跑的程序有两类,一类是PHP的,如Wordpress、Joomla、Zenphoto,或是基于Yii开发的一些程序,另外一类是Perl的,像Movable Type。

升级PHP至5.4.x

之前的PHP版本是5.3.x,因为要配置Nginx+php-fpm,因此升到5.4.x(顺便可以试试Yii2),PHP的升级就用apt-get的模式搞定了,PHP5.4.x已经带了php-fpm,所以不用自己再操心。

升级完PHP5.4后,检查php-fpm的配置,打开/etc/php5/fpm/pool.d/www.conf,修改为自己定义的用户与用户组,比如”www-data”:

; Unix user/group of processes
user = www-data
group = www-data

我安装完成之后,默认的listen是透过sock文件,我将之修改为透过9000端口,并将原来的注释掉:

listen = 127.0.0.1:9000
;listen = /var/run/php5-fpm.sock

其他的配置就不再赘述,网上一搜一大把,修改完配置就是重启php-fpm了。

/etc/init.d/php5-fpm restart

安装Tengine

Tengine的安装应该说是容易的,不过刚好我找到一篇文章《制作Debian风格的Tengine deb包》,讲的是如何制作Tengine的deb安装包,开启DSO支持,动态加载自己想要的模块,正合我意。于是我便按部就班地制作了deb安装包,并用于最终的安装。如果你的Debian是32位,而且也不想折腾的话,可以下载我制作的Debian 32位deb安装包(更新至2.0.0)试试看,配置的风格基本上与文章中的一致,只是添加了一些依赖包,另外为了更符合Debian的风格,添加了”sites-available”和”sites-enabled”两个目录,如果你用惯了Debian风格的Apache或Nginx,这应该会让你更熟悉一些。

先按照原文的说明安装以下依赖包:

apt-get install libxml2
apt-get install libxslt1.1
apt-get install libxslt1-dev
apt-get install libgd2-xpm libgd2-xpm-dev
apt-get install libgeoip1 libgeoip-dev
apt-get install libssl-dev
apt-get install libpcre3 libpcre3-dev
apt-get install libssl0.9.8

然后再用dkpg -i XXX.deb安装tengine

随后要load几个动态库,以支持Rewrite、PHP,因为我有些部分需要进行访问控制 ,所以还load了access模块。

dso {
load ngx_http_fastcgi_module.so;
load ngx_http_rewrite_module.so;
load ngx_http_access_module.so;
}

配置虚拟主机支持PHP

我的做法是在nginx.conf中添加名为php的upstream,并在虚拟主机的server配置中使用它,ngxin.conf的配置在http{…}中增加以下内容:

upstream php {
server 127.0.0.1:9000;
}

在虚拟主机配置文件的server{…}中增加以下内容:

#index配置中增加index.php
index  index.php index.html index.htm;
#添加php支持,fastcgi_pass配置的php就是ngxin.conf中配置的upstream php{}
location ~ \.php$ {
fastcgi_pass php;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

安装并配置fcgiwrap

这部分我参考了Nginx网站中关于Fcgiwrap这一章,大概就是这样:

aptitude install fcgiwrap

因为listen是透过socket文件,位置在”/var/run/fcgiwrap.socket”,如果fcgiwrap启动用户的权限不正确的话,是无法通讯的,因此如果有修改修改fcgiwrap的启动用户,可打开”/etc/init.d/fcgiwrap”,直接修改里面的FCGI_USERFCGI_GROUP

配置虚拟主机支持Perl

和配置虚拟主机支持PHP差不多,在虚拟主机配置文件的server{…}中增加以下内容,这回是没有配置upstream的情况(懒得了):

location ~ \.cgi$ {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.cgi;
include fastcgi_params;
}

rewrite规则修改

以上部分折腾完后,就需要修改rewrite规则了,这部分是与Apache差异比较大的地方,我一时没能适应,但是Nginx提供了相当多具体的Rewrite的文档,如WordPressZenphoto,因此这个步骤没有遇到什么特别的困难。以下我列出我的配置,可能与文档中的不尽相同,只是供参考吧。

Joomla

location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
return 403;
error_page 403 /403_error.html;
}
error_page   500 502 503 504  /var/www/50x.html;
location = /50x.html {
root   /var/www;
}
location ~* \.(ico|pdf|flv)$ {
expires 1y;
}
location ~* \.(js|css|png|jpg|jpeg|gif|swf|xml|txt)$ {
expires 14d;
}
location / {
try_files $uri $uri/ /index.php?$args;
}

WordPress

location ~* \.(png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location / {
try_files $uri $uri/ /index.php?$args;
}

Zenphoto

location ~ \.php$ {
fastcgi_pass php;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
}
location ~* \.(ico|pdf|flv)$ {
expires 1y;
}
location ~* \.(js|css|png|jpg|jpeg|gif|swf|xml|txt)$ {
expires 14d;
}
location @zenphoto {
# experimental rss rules
rewrite index\.php\?^rss-(.*)&(.*)    /index.php?rss=$1 last;
rewrite index\.php\?^rss-(.*)$        /index.php?rss=$1 last;
rewrite index\.php$ /index.php last;
rewrite ^/(.*)/page/([A-Za-z0-9_\-]+)/?$ /index.php?album=$1&page=$2 last;
# Images and stuff
rewrite "^/(.*)/image/(thumb|[0-9]{1,4})/([^/\\\]+)$"  /zp-core/i.php?a=$1&i=$3&s=$2  last;
rewrite ^/(.*)/image/([^/\\\]+)$  /zp-core/i.php?a=$1&i=$2  last;
rewrite "^/(.*)/album/(thumb|[0-9]{1,4})/([^/\\\]+)$"  /zp-core/i.php?a=$1&i=$3&s=$2&album=true  last;
# Catch all for unknown stuff
rewrite ^/(.*)/?$ /index.php?album=$1 last;
}
location @albums {
rewrite ^/albums/?(.+/?)?$  /$1  redirect;
}
# Admin pages
location /admin {
rewrite ^/admin/?$ /zp-core/admin.php redirect;
}
location /albums {
try_files $uri @albums;
}
# Tiny URLs
location /tiny {
rewrite ^/tiny/([0-9]+)/?$ /index.php?p=$1&t last;
}
# Page
location /page {
rewrite ^/page/([0-9]+)/?$ /index.php?page=$1 last;
rewrite ^/page/([A-Za-z0-9\-_]+)/?$ /index.php?p=$1 last;
rewrite ^/page/([A-Za-z0-9_\-]+)/([0-9]+)/?$ /index.php?p=$1&page=$2 last;
}
# Pages
location /pages {
rewrite ^/pages/?$ /index.php?p=pages last;
rewrite ^/pages/(.*)/?$ /index.php?p=pages&title=$1 last;
}
# Search
location /page/search {
rewrite ^/page/search/fields([0-9]+)/(.*)/([0-9]+)/?$ /index.php?p=search&searchfields=$1&words=$2&page=$3 last;
rewrite ^/page/search/fields([0-9]+)/(.*)/?$ /index.php?p=search&searchfields=$1&words=$2 last;
rewrite ^/page/search/archive/(.*)/([0-9]+)/?$ /index.php?p=search&date=$1&page=$2 last;
rewrite ^/page/search/archive/(.*)/?$ /index.php?p=search&date=$1 last;
rewrite ^/page/search/tags/(.*)/([0-9]+)/?$ /index.php?p=search&searchfields=tags&words=$1&page=$2 last;
rewrite ^/page/search/tags/(.*)/?$ /index.php?p=search&searchfields=tags&words=$1 last;
rewrite ^/page/search/(.*)/([0-9]+)/?$ /index.php?p=search&words=$1&page=$2 last;
rewrite ^/page/search/(.*)/?$ /index.php?p=search&words=$1 last;
}
# News
location /news {
rewrite ^/news/?$ /index.php?p=news last;
rewrite ^/news/([0-9]+)/?$ /index.php?p=news&page=$1 last;
rewrite ^/news/category/(.*)/([0-9]+)/?$ /index.php?p=news&category=$1&page=$2 last;
rewrite ^/news/category/(.*)/?$ /index.php?p=news&category=$1 last;
rewrite ^/news/archive/(.*)/([0-9]+)/?$ /index.php?p=news&date=$1&page=$2 last;
rewrite ^/news/archive/(.*)/?$ /index.php?p=news&date=$1 last;
rewrite ^/news/(.*)/?$ /index.php?p=news&title=$1 last;
}
# Root
location / {
try_files $uri $uri/ @zenphoto;
}

Yii

location / {
try_files $uri $uri/ /index.php;
}

ShopEx

location / {
if (!-e $request_filename) {
rewrite ^/(.+\.(html|xml|json|htm|php|jsp|asp|shtml))$ /index.php?$1 last;
}
}

完结

这样,就已经完成了从Apache2到Tengine(Nginx)的迁移,用用看吧,感觉还不错。别忘了修改完虚拟主机配置后要重启Nginx或重新应用配置,我用惯了重启,所以……。

/etc/init.d/nginx restart