nginx采用默認安裝即可。

php with php-fpm patch

php需要先打上php-fpm的patch,以使之能生成php-fpm命令。参考:http://php-fpm.org/wiki/Documentation

php-fpm patch的下載地址為:http://php-fpm.org/downloads/,找到與使用的php版本一致的,diff文件也可以。

(我用的是5.2.5的php,在测试环境,patch是5.2的,结果make的时候就报错:undefined reference to `pestrndup’。去更高版本的php里程看看,是在Zend/zend_alloc.h中定义的宏,但是5.2.5中没有。)

(还是给我报错!郁闷了,想起来打patch的时候报了一堆fail,更换php为5.2.6版本,与线上一致,省得我处理完一个问题到线上遇到新的……)

cd /path/to/phpsrc; patch -p1 < /path/to/fpm.patch ( 注意,要找一个干净的版本,如果之前打过错误的patch!!)

./buildconf –force # 强制patch生效, 其实php-5.2.*是不需要这一步的;当前,php-5.3.*时需要,因为对应的patch是不稳定版本

config php的時候,需要注意,–with-apxs2代表Build shared Apache 2.0 Handler module,所以不要加上這個選項。

‘./configure’  ‘–prefix=/usr/local/phpcgi’ ‘–with-config-file-path=/usr/local/phpcgi/etc’ ‘–enable-fastcgi’ ‘–enable-force-cgi-redirect’  ‘–enable-fpm’ ‘–enable-dba’ ‘–with-db4′ ‘–enable-sockets’ ‘–with-curl’ ‘–enable-soap’ ‘–enable-ftp’ ‘–enable-libxml’ ‘–with-libxml-dir’ ‘–with-mcrypt’ ‘–with-zlib’ ‘–enable-pdo’ ‘–with-pdo-dblib’ ‘–with-mhash’ ‘–enable-bcmath’ ‘–with-openssl’ ‘–with-mysql=/usr/local/mysql’  –enable-mbstring –enable-zip –with-gd –with-jpeg-dir=/usr/lib/libjpeg.so –with-pdo-mysql=/usr/local/mysql/ –with-mysqli=/usr/local/mysql/bin/mysql_config

make ; sudo make install

这时会在安装目录下生成sbin/php-fpm和etc/php-fpm.conf。

继续配置php-fpm.conf,这里有static和apache-like两种pm模式。

php扩展

memcache

tokyo_tyrant

mslib

eaccelerator

记得每次安装完扩展之后,要重启或者reload php-fpm。

nginx的rewrite配制

由于默认的配置下,PHP无法获取到类似$_SERVER[PHP_SELF]之类的变量,需要include fastcgi.conf。

user  apache apache;
worker_processes  4;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
        use epoll;
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

        log_format  access  '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for';
    access_log  logs/access.log access;

    sendfile        on;
    #tcp_nopush     on;
        tcp_nodelay     on; 

    #keepalive_timeout  0;
    keepalive_timeout  65;

        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 64k;
        fastcgi_buffers 4 64k;
        fastcgi_busy_buffers_size 128k;
        fastcgi_temp_file_write_size 128k;

        gzip on;
        gzip_min_length  1k;
        gzip_buffers     4 16k;
        gzip_http_version 1.0;
        gzip_comp_level 2;
        gzip_types    text/plain application/x-javascript text/css application/xml;
        gzip_vary on;

    server {
        listen       80;
        server_name  localhost;

                location ~ ^/status/ {
                        stub_status on; #Nginx 状态监控配置
                        access_log off;
                }
        }

        server {
                listen       80;
                server_name  test.try8.info;
                index index.html index.htm index.php;
                root  /ms/wwwroot/test/;

                location ~ .*\.(php)?$
                {
                        fastcgi_pass  127.0.0.1:9000;
                        fastcgi_index index.php;
                        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                }
        }

        server
        {
                listen       80;
                server_name  qq.try8.info sina.try8.info yoka.try8.info renren.try8.info;
                index index.html index.htm index.php;
                root  /ms/wwwroot/stry_v2/;

                location ~* .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires      30d; }
                location ~* .*\.(js|css)$ { expires      30d; }
                location ~* .*\.(html)$ {expires 1d;}

                rewrite ^/webroot/(.*)$  /app/webroot/$1 break;
                rewrite ^/(xfiles.*)/(.*)$  /app/$1/$2 break;
                rewrite ^/((?!index\.php|tryapp/TryAppManagement).*)$            /index.php/$1 break;

                location ~ .*\.php{
                        fastcgi_pass  127.0.0.1:9000;
                        fastcgi_index index.php;
                        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                        include fastcgi.conf;
                }
        }

        server {
                listen       80;
                server_name  itry.try8.info i.try8.info;
                index index.html index.htm index.php;
                root  /ms/wwwroot/happy_itry_v2/;

                location ~* .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires      30d; }
                location ~* .*\.(js|css)$ { expires      30d; }
                location ~* .*\.(html)$ {expires 1d;}

                rewrite "^/([^/]+)/admin(?:/(?:[-/_a-zA-Z0-9]+\.php)?)?$"  "/$1/admin/dispatch.php" break;
                rewrite ^/([^/]+)/[-/_a-zA-Z0-9]+\.php  /$1/dispatch.php    break;
                rewrite "^/([^/]+)/([^./]*)(?:/([^.?]*))?(?:\?(.*))?$"    "/$1/dispatch.php?control=$2&args=$3&$4&$query_string"  break;

                location ~ .*\.php{
                        fastcgi_pass  127.0.0.1:9000;
                        fastcgi_index index.php;
                        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                        include fastcgi.conf;
                }
        }

}

nginx 403 & 404错误

启动php-fpm和nginx,本地配置host访问,访问http://localhost/index.html是403错误,http://localhost/index.php是404错误。这些都是由于权限导致的。

index.html是由nginx直接产生的,index.php的错误则是由php-fpm导致的。

首先,需要保证代码所在目录、文件及其递归的父目录都是可以被nginx的user read的!其次,还要保证这些目录和文件也能够被php-fpm的user read!

然后,reload nginx和php-fpm即可。

性能测试与优化

nginx与apache的一个较大的区别是,它利用了linux2.6的epoll,而非之前的select或poll。这样就可以避免select模式下,轮询去查看是否有ready的端口,而是以事件驱动的方式去获取到ready的读写端口。

nginx一般不会配置成使用很多个worker_process,有人说配置为cpu核数*2。而每个worker_process可以同时处理的连接数目就是用workder_connections来配置的。由于采用了epoll的方式,当worker处理无阻塞事件时会一直处理直至完成或阻塞(个人猜测,或许也会有time上限,没看源码哈),一旦遇到阻塞,则继续处理下一事件。这样的好处是能够最大限度的发挥系统的性能。

由于nginx会把动态请求转发给php-fpm处理,所以动态请求优化,我认为就是针对php-fpm的优化了。

当nginx的worker_processes为8,采用epoll,worker_connectins=1024;php-fpm 使用static的pm方式,并且max_children=64的时候,访问有数据库(前端有memcached缓存)访问的页面,没有加eAccelerator加速器的时候,QPS只能达到40。加上eAccelerator,QPS达到150左右。

将上面的worker_connections改为65535,并更改响应的ulimit,QPS反而下降到100左右。

访问同样的页面,使用apache,QPS是37。

————————————————————–

2012-03-16

针对新买的虚拟服务器做了性能测试,centos,2.6.18核,nginx1.14,php5.3,使用php-fpm。使用http_load作为压力测试工具。

2核4G内存:
QPS 90+-(必须使用memcached,否则性能很差),cpu100%,load20+,  http_load使用不同的参数组合,基本不变,php-fpm配置为dynamic模式,则nginx的errorlog中有timout:connect() failed (110: Connection timed out) while connecting to upstream
QPS 70+- ,static,无timeout,cpu100%,load20+
(可通过pstree | grep php-fpm查看当前php-fpm子进程个数)
4核8G内存,php-fpm dynamic, max_children 128:CPU idle65% , 负载个位数,不超过8
-parallel 200 -fetches 2000  QPS 170
-parallel 300 -fetches 3000  QPS 120 (有connect timeout了)推测是来不及clone子进程,故改为static测试如下
4核8G内存,php-fpm static, max_children 256:CPU idle65% , 负载个位数,不超过8
-parallel 300 -fetches 3000  QPS 150 (无connect timeout了)

在2核4G机器上测试时,dynamic模式,即使timeout出现时,php-fpm进程数都没有达到pool的max_children个数,启动个数是5,最大个数是128,在短期大量请求时,只能达到六七十个php进程。同时cpu使用100%,us大约80%-90%,负载达到30左右。strace挂到php-fpm master进程上看时,发现clone请求时有略微停顿。所以,猜测是,瓶颈在cpu,php子进程已经占用了大量的cpu资源,本来就在相互竞争cpu了,同时也导致master进程无法快速增加子进程,所以造成响应缓慢,QPS也不高

2 Comments

  1. xinweifeng says:

    也改用nginx了?

  2. admin says:

    是的,准备迁移呢~

Leave a Reply