就个人经验来说,从apache切换到nginx上不是很难,关键是你需要分析好现有apache配置的内容,剩下的就是在nginx中对应配置就行。以本人的apache配置为例:
- 关闭服务器版本显示
- 单独的用户
- worker&event
- 与PHP的整合
- init.d脚本(个人是编译安装的)
- gzip
- expires(图片等过期时间设置)
- 虚拟主机
- wordpress的permlink
- 二级域名的重定向(错误的配置)
最后一个是我对apache虚拟主机配置不完全理解导致的一个失误,nginx上当然不会把错误照搬过来,但是nginx上需要做以前的链接兼容(这么快就有历史包袱了……)。
在做完功能分析之后,个人建议在虚拟机中搭建一套类似环境练手。除非你现有的apache是个实验环境,临时关个一两天没啥问题,否则还是老老实实做模拟练习。
即使是模拟练习也不要奢望一次成功,个人认为类似敏捷中的快速反馈——是逐个迁移功能的方式比较好。而且迁移的功能尽量按照难度由低到高的顺序排序,特别是在功能列表很长时,因为这样实施起来更有信心。
安装nginx的过程这里就不展开了,一搜一大把,官方wiki的在这里,我这里也有一个。
服务器版本显示
基于安全考虑,建议不显示服务器的版本。apache上配置如下:
ServerTokens Prod;
nginx上配置如下:
http { server_tokens off; }
注意nginx的配置末尾是有分号的,和apache不一样。其次nginx的server_tokens上下文为http,server,location,而apache的可以配置在顶层。
顺便说一句,nginx和apache一样也有指令文档,nginx的在这里。
单独的用户
apache使用unixd_module限制用户,配置如下:
LoadModule unixd_module modules/mod_unixd.so <IfModule unixd_module> User apache Group apache </IfModule>
nginx的指令如下:
user www-data www-data;
nginx的用户默认值为nobody。
worker和event
apache有多种选择,个人选择mpm_event,指令数据是ab渐进出来的。
<IfModule mpm_event_module> StartServers 2 MinSpareThreads 1 MaxSpareThreads 4 ThreadsPerChild 4 MaxRequestWorkers 4 MaxConnectionsPerChild 1000 </IfModule>
nginx因为模型不一样,所以配置角度不一样,主要配置项是worker_processes,工作进程数:
worker_processes 1; events { use epoll; worker_connections 1024; }
虽然apache和nginx模型不一样,但都可以用ab做压力测试,重点是保证内存使用量在合理范围内。
与PHP的整合
apache的网上一搜索一大把,我实际使用的:
LoadModule dir_module modules/mod_dir.so <IfModule dir_module> DirectoryIndex index.html index.php </IfModule> LoadModule php5_module modules/libphp5.so <FilesMatch \.php$> SetHandler application/x-httpd-php </FilesMatch>
nginx与php的连接方式个人选择php-fpm,并且使用unix socket文件而不是socket方式:
http { server { location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } }
注意php-fpm需要单独启动。其次默认的fastcgi_param配置值是/scripts$fastcgi_script_name,个人测试时没法用,会报File not found,需要修改成$document_root$fastcgi_script_name。
测试时建议写个带phpinfo的简单index.php。
<?php phpinfo(); ?>
如果你看到熟悉的phpinfo界面说明nginx和php整合OK了。
init.d脚本
apache的话用apachectl就行,nginx需要另外找。个人选择的是nginx的wiki上的针对ubuntu的脚本,使用时注意要修改脚本中程序位置,配置位置和PID位置:
#------------------------------------------------------------------------------ # Consts #------------------------------------------------------------------------------ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # change to /usr/local/nginx/sbin/nginx DAEMON=/usr/local/sbin/nginx PS="nginx" PIDNAME="nginx" #lets you do $PS-slave PIDFILE=$PIDNAME.pid #pid file # change to /usr/local/nginx/logs PIDSPATH=/var/run DESCRIPTION="Nginx Server..." RUNAS=root #user to run as SCRIPT_OK=0 #ala error codes SCRIPT_ERROR=1 #ala error codes TRUE=1 #boolean FALSE=0 #boolean lockfile=/var/lock/subsys/nginx # default is OK NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
nginx配置中pid位置用pid指令指定:
user www-data www-data; worker_processes 1; pid /var/run/nginx.pid; events { use epoll; worker_connections 1024; }
给init.d脚本取个名字,比如nginx,放到/etc/init.d中,确保可执行(chmod +x),最后执行update-rc.d nginx defaults加入启动列表。
接下来你就可以通过service nginx start启动nginx,service nginx stop关停nginx了。顺便说一句,没有init.d脚本时,使用nginx启动,nginx -s stop停止和nginx -s reload重启。
php-fpm实际上也需要一个init.d脚本。这里就不展开,详细的可以看这里。
gzip
apache下使用deflate模块:
LoadModule deflate_module modules/mod_deflate.so <IfModule deflate_module> AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE text/javascript BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html </IfModule>
nginx的配置(和apache不完全对应,注意content-type):
gzip on; gzip_min_length 1k; gzip_comp_level 2; gzip_types text/plain text/javascript application/x-javascript text/css;
各参数详细含义请参考这里。
gzip的检查方法有很多,个人使用firebug对比前后content-length。
expires
apache下使用expires模块:
LoadModule expires_module modules/mod_expires.so <IfModule expires_module> ExpiresActive on ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/gif "access plus 1 month" </IfModule>
nginx下expires指令:
location ~ \.(gif|jpg|jpeg|png|bmp)$ { expires 15d; }
一个是按照content-type,另外是按照扩展名,一般来说不会有问题。
个人检查expires的方法是用firebug查看图片的响应头。
虚拟主机
虚拟主机是apache的词,nginx只有server block。
比如下面这段虚拟主机配置:
<VirtualHost *:80> ServerName foo.bar ServerAlias www.foo.bar DocumentRoot /home/foo/public_html <Directory "/home/foo/public_html"> Options Indexes AllowOverride FileInfo Require all granted </Directory> </VirtualHost>
映射foo.bar, www.foo.bar到/home/foo/public_html目录。
nginx对应配置为:
http { server { server_name foo.bar www.foo.bar root /home/foo/public_html; location / { index index.html index.html; } } }
注意两者还是有些地方不对等的,比如apache的FileInfo代表允许.htaccess,nginx没有.htaccess,所以要用另外的方式支持相应的功能,比如.htaccess中的rewrite。大部分情况下,不同域名对应不同目录还是很容易转换的。
permanent link
permanent link是在wordpress中设置的,但是需要web服务器支持。apache的话需要开启.htaccess,注意上面虚拟主机中的FileInfo。nginx的话用另外一种方案:
http { server { location / { index index.html index.htm index.php; try_files $uri $uri/ /index.php?args; } } }
注意其中的try_files。
二级域名重定向
简单来说,我配置了blog.xnnyygn.in跳转到xnnyygn.in/blog,但是在配置nginx的时候,发现我对虚拟主机理解错了,二级域名可以直接映射到目录的。但是考虑到之前给的链接,我决定用nginx的rewrite做兼容。
http { server { location /blog/ { rewrite ^/blog/(.*)$ http://blog.xnnyygn.in/$1 permanent; } } }
这里的rewrite很简单,只要懂正则表达式基本就能明白。我的要求是遇到/blog/下的请求,把后面的内容转发到/下,并且是永久的。
总结
上面介绍了从apache切换到nginx涉及到的常见问题。如果你是第一次配置nginx的话,建议从简单的配置点开始逐步平滑切换。遇到问题可以google。nginx作为一个出现有好几年并且并很多大公司使用的web服务器,相关教程,wiki和问题解答都很多,足以解决你遇到的大部分问题。
4 responses to “wordpress的webserver从apache切换到nginx”
XY有试过wordpress开multi site吗
没有,觉得比较麻烦。而且个人认为多作者博客比多博客要好一些……
我们现在是4个人拼VPS的,然后很多人都要用自己的wordpress。有童鞋需要两个wordpress,然后现在就有4个wordpress了。维护的时候,四个wordpress都要分别管理,看起来很麻烦。我前几天一直在尝试multi site,但是一直没成功过。。。
具体有哪些问题?(这里回复嵌套太深了,twitter或者gmail回吧……)
如果是调试multisite,建议搞个虚拟机自己练练手。这个博客我也是调试了一两个星期才上的。