我用的是BuyVM.net一年$15的VPS,可想而知这个主机的配置是如何Economy: 128M 内存。原来使用的是Apache 1.3 prefork 和 Php_mod,系统稳定性非常好,然而性能可以说令人失望,打开一个简单的静态页面平均需要3秒,而使用wordpress及若干plugin后,差不多需要10秒以上才能访问页面,而且这是打开WP-Supercache后的性能。据我的观察,这是因为Apache进程会fork出很多子进程,这些进程吃掉了有限的VPS内存。2月的最后一天,我决定试一试传说中Nginx,看看它在小内存的VPS上表现是否优异。在8000端口打开Nginx后,使用http://whichloadsfaster.com/和ab – Apache HTTP server benchmarking tool 比较Nginx和Apache的速度,毫无悬念的,Nginx要快,平均只用了1/4的时间。因此我下定决心,将整个VPS升级到Nginx+PHP FPM。具体的步骤如下:
1. 升级Ubuntu 10.04 LTS Lucid 到 10.10 Maverick
升级的目的是使用Ubuntu官方的PHP,因为只有10.10版的PHP5才包括了php5-fpm功能。
具体方法(翻译自http://www.howtoforge.com/how-to-upgrade-ubuntu-10.04-lucid-lynx-to-10.10-maverick-meerkat-desktop-and-server-p2):
aptitude install update-manager-core
改变 /etc/update-manager/release-upgrades 中Prompt=normal
do-release-upgrade
我在升级中反复遇到关于procps的这个提示:start: Unknow Jobs: procps
解决方法就是建立一个/etc/init/procps.conf,然后继续apt-get upgrade就行。
原理是service 这个命令会调用/etc/init.d下面的脚本,而procps的脚本会用start命令,start procps命令会调用initctl start procps, 这个过程中需要/etc/init/procps.conf来设定procps相关的参数。在ubuntu升级的时候,这个配置文件缺失造成了上述问题。
2. 安装Nginx
先卸载Apache, 用apt-get install nginx就行,之后参考:
http://www.howtoforge.com/installing-nginx-with-php-5.3-and-php-fpm-on-ubuntu-lucid-lynx-10.04-without-compiling-anything
我这里也列出了自己的nginx.conf文件内容,注意我使用了rewrite功能。这一功能在Apache里是用mod_rewrite支持,在.htaccess里指定的。我们写在nginx.conf文件里也不复杂。另外,末尾的backend语句似乎是必须的,没有它PHP似乎就无法工作。
My /etc/nginx/nginx.conf
user www-data;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 1024;
# multi_accept on;
}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
tcp_nodelay on;
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
My /etc/nginx/sites-enabled/default
server {
listen 8080;
server_name zhanxw.com;
access_log /var/log/nginx/localhost.access.log;
root /var/www;
## Default location
location / {
root /var/www;
index index.php index.html;
}
location /blog/ {
index index.php;
if (-e $request_filename) {
break;
}
rewrite ^/blog/(.+)$ /blog/index.php?q=$1 last;
}
## Images and static content is treated different
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
access_log off;
expires 30d;
root /var/www;
}
## Parse all .php file in the /var/www directory
location ~ .php$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
## Images and static content is treated different
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml)$ {
access_log off;
expires 30d;
root /var/www;
}
## Parse all .php file in the /var/www directory
location ~ .php$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
## Disable viewing .htaccess & .htpassword
location ~ /\.ht {
deny all;
}
}
upstream backend {
server 127.0.0.1:9000;
}
3. 安装PHP FPM
使用apt-get install php5-fpm php-apc php5-cgi php5-cli php5-mysql php5-common php-pear php5-curl php5-suhosin php5-gd php5-imagick imagemagick php5-mhash php5-mcrypt即可。
注意安装后可以用service php5-fpm start来检查是否有缺失的php5模块。例如如果见到:
* Starting PHP5 FPM… PHP Warning: PHP Startup: Unable to load dynamic library ‘/usr/lib/php5/20090626+lfs/mcrypt.so’ – /usr/lib/php5/20090626+lfs/mcrypt.so: cannot open shared object file: No such file or directory in Unknown on line 0
Feb 27 15:40:28.053288 [WARNING] [pool www] pm.start_servers is not set. It’s been set to 10.
这说明应该安装php5-mcrypt。后面的WARNING可以忽略。
另外,小内存VPS上使用PHP-FPM可以控制其进程个数。在我的VPS上,单个PHP-FPM可以使用多达100M的内存,同时我的访问量很少,因此我设置PHP-FPM使用static方式维持2个进程。从实践来看系统可以保持合理的响应时间,同时内存不会被用光。
我的PHP-FPM 的配置文件/etc/php5/fpm/pool.d/www.conf 列在下面:
...
; Choose how the process manager will control the number of child processes.
; Possible Values:
; static - a fixed number (pm.max_children) of child processes;
; dynamic - the number of child processes are set dynamically based on the
; following directives:
; pm.max_children - the maximum number of children that can
; be alive at the same time.
; pm.start_servers - the number of children created on startup.
; pm.min_spare_servers - the minimum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is less than this
; number then some children will be created.
; pm.max_spare_servers - the maximum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is greater than this
; number then some children will be killed.
; Note: This value is mandatory.
pm = static
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 2
...
4.安装eAccelerator
主要参考:http://developer.mindtouch.com/en/kb/Improve_PHP_performance_with_eAccelerator_on_Ubuntu_8.04_(Debian)
基本上下载,编译,安装。之后在php.ini中加入下面几行即可(注意.so文件的路径):
; eAccelerator configuration
; Note that eAccelerator may also be installed as a PHP extension or as a zend_extension
; If you are using a thread safe build of PHP you must use
; zend_extension_ts instead of zend_extension
;extension = "/usr/lib/php5/20060613+lfs/eaccelerator.so"
zend_extension = "/usr/lib/php5/20090626+lfs/eaccelerator.so"
eaccelerator.shm_size = "16"
eaccelerator.cache_dir = "/var/cache/eaccelerator"
eaccelerator.enable = "1"
eaccelerator.optimizer = "1"
eaccelerator.check_mtime = "1"
eaccelerator.debug = "0"
eaccelerator.filter = ""
eaccelerator.shm_max = "0"
eaccelerator.shm_ttl = "0"
eaccelerator.shm_prune_period = "0"
eaccelerator.shm_only = "0"
eaccelerator.compress = "1"
eaccelerator.compress_level = "9"
eaccelerator.allowed_admin_path = "/var/www/eaccelerator"
安装完之后注意检查<?php phpinfo(); ?>页面的输出,保证eAccelerator开启。
5. 启用Varnish
偶然间听说Varnish可以做代理,提供系统响应速度。以我的经验来看,对于静态页面,通过Varnish获取页面和直接使用nginx差别不大(动态页面未测试)。但用Varnish在80端口监听,听起来可以把真正的服务器挡在Varnish之后,似乎可以增强安全性吧。我在VPS上安装Varnish,应注意Varnish本意的版本变化较快,在配置时应注意路径的变化。需要配置两个文件,第一个是
/etc/default/varnish 应改成START=yes,否则会出现这个错误Not starting HTTP accelerator varnishd (http://twitter.com/#!/grosser/status/5249558112108544);另一个是/etc/varnish/default.vcl,我参考了http://wowubuntu.com/varnish.html 以及http://blog.mudy.info/2009/04/my-varnish-vcl-for-wordpress/,这里列出我的配置文件/etc/varnish/default.vcl:
backend default {
.host = "localhost";
.port = "8080";
}
acl purge {
"localhost";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
return(lookup);
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_hit {
if (req.request == "PURGE") {
set obj.ttl = 0s;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
error 404 "Not in cache.";
}
if (!(req.url ~ "wp-(login|admin)")) {
unset req.http.cookie;
}
if (req.url ~ "^/[^?]+.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)(\?.|)$") {
unset req.http.cookie;
set req.url = regsub(req.url, "\?.$", "");
}
if (req.url ~ "^/$") {
unset req.http.cookie;
}
}
sub vcl_fetch {
if (req.url ~ "^/$") {
unset beresp.http.set-cookie;
}
if (!(req.url ~ "wp-(login|admin)")) {
unset beresp.http.set-cookie;
}
}
插曲1:重置MySQL密码
好就不用MySQL的root密码,重置密码(适用于MySQL 5.1)可以参考:
Generic method http://dev.mysql.com/doc/refman/5.1/en/resetting-permissions.html
只需要3步:以--skip-grant-tables
参数启动Mysql-server;启动mysql;执行
UPDATE mysql.user SET Password=PASSWORD('MyNewPass') WHERE User='root';
FLUSH PRIVILEGES;
插曲2:使Firefox 支持Java Applets
在设置PHP-FPM 参数不当时,有可能整个VPS的内存全部被吃光,这时没法用SSH登录,很多命令(sudo、ls、top)都无法执行,这时候可以用BuyVM.net 提供的 manage.buyvm.net 页面,以Java Applets方式以root身份登录到VPS。默认情况下,Ubuntu的Firefox不支持Java Applets,解决方法就是安装:icedtea6-plugin .
另附:Wordpress中插入代码的方法:
注意这里使用了中文的全角括号,以免Wordpress当成真正的代码。
【sourcecode language=”css”】
your code here
【/sourcecode】
具体的语言可以有:
- actionscript3
- bash
- coldfusion
- cpp
- csharp
- css
- delphi
- erlang
- fsharp
- diff
- groovy
- javascript
- java
- javafx
- matlab (keywords only)
- objc
- perl
- php
- text
- powershell
- python
- r
- ruby
- scala
- sql
- vb
- xml
http://en.support.wordpress.com/code/posting-source-code/