Nginx PHP 比 Apache 2.2 总是慢

3
在使用Ubuntu 13.04上的完全原始软件包运行Apache 2.2和Nginx 1.2.6进行负载测试时,我发现Nginx PHP请求的性能始终低于Apache PHP请求的性能;如果可能的话,我正在寻求指导,使我们的Nginx在所有情况下的性能都高于Apache
Apache设置相当标准,但Nginx设置被大量定制;它们在基准测试结果下面列出
我使用名为Siege v3.0.2(http://www.joedog.org/siege-home/)的基准测试工具为单个并发用户(c1),10个并发用户(c10)和100个并发用户(c100)生成结果;结果如下: Apache结果:
      Date & Time,  Trans,  Elap Time,  Data Trans,  Resp Time,  Trans Rate,  Throughput,  Concurrent,    OKAY,   Failed
**** c1 Apache Static ****
2013-08-01 00:54:12,   5982,      59.23,         338,       0.01,      101.00,        5.71,        1.00,    5982,       0
**** c1 Apache PHP ****
2013-08-01 00:55:12,    549,      59.98,          88,       0.11,        9.15,        1.47,        1.00,     549,       0
**** c1 Apache Combined ****
2013-08-01 00:56:12,   1609,      59.98,         139,       0.04,       26.83,        2.32,        1.00,    1609,       0
**** c10 Apache Static ****
2013-08-01 00:57:12,  35983,      59.97,        2039,       0.02,      600.02,       34.00,        9.99,   35983,       0
**** c10 Apache PHP ****
2013-08-01 00:58:12,   3769,      59.98,         610,       0.16,       62.84,       10.17,        9.99,    3769,       0
**** c10 Apache Combined ****
2013-08-01 00:59:12,  10928,      59.98,         947,       0.05,      182.19,       15.79,        9.99,   10928,       0
**** c100 Apache Static ****
2013-08-01 01:00:12,  44581,      59.97,        2523,       0.13,      743.39,       42.07,       98.63,   44581,       0
**** c100 Apache PHP ****
2013-08-01 01:01:12,   4427,      59.98,         721,       1.32,       73.81,       12.02,       97.34,    4427,       1
**** c100 Apache Combined ****
2013-08-01 01:02:12,  12735,      59.98,        1125,       0.47,      212.32,       18.76,       99.68,   12735,       0

Nginx结果:

      Date & Time,  Trans,  Elap Time,  Data Trans,  Resp Time,  Trans Rate,  Throughput,  Concurrent,    OKAY,   Failed
**** c1 Nginx Static ****
2013-08-01 02:36:13,   9040,      59.10,         274,       0.01,      152.96,        4.64,        1.00,    9040,       0
**** c1 Nginx PHP ****
2013-08-01 02:37:13,    581,      59.98,          18,       0.10,        9.69,        0.30,        1.00,     581,       0
**** c1 Nginx Combined ****
2013-08-01 02:38:13,   1786,      59.59,          55,       0.03,       29.97,        0.92,        1.00,    1786,       0
**** c10 Nginx Static ****
2013-08-01 02:39:13,  44557,      59.98,        1353,       0.01,      742.86,       22.56,        9.99,   44557,       0
**** c10 Nginx PHP ****
2013-08-01 02:40:13,   3766,      59.98,         120,       0.16,       62.79,        2.00,        9.98,    3766,       0
**** c10 Nginx Combined ****
2013-08-01 02:41:13,  10962,      59.98,         339,       0.05,      182.76,        5.65,        9.98,   10962,       0
**** c100 Nginx Static ****
2013-08-01 02:42:13,  54463,      59.98,        1642,       0.11,      908.02,       27.38,       99.70,   54463,       0
**** c100 Nginx PHP ****
2013-08-01 02:43:13,   3649,      59.98,         117,       1.62,       60.84,        1.95,       98.70,    3649,       0
**** c100 Nginx Combined ****
2013-08-01 02:44:13,  10802,      59.98,         334,       0.55,      180.09,        5.57,       98.63,   10802,       0

我关心的数据来自于c100“PHP”和“Combined”结果。Apache相当快,我想知道为什么会这样,考虑到所有在线基准测试都表明相反的情况。
两个服务器都是:
1. 采用四核Xeon处理器 2. 8GB内存 3. 连接到同一网络上的MongoDB v2.2数据库 4. PHP-FPM设置为使用100个PHP进程
Apache(设置非常接近原始状态):
1. 运行在CentOS 5上 2. Apache 2.2 3. mod_php Nginx:
1. Ubuntu 13.04 2. Nginx 1.2.6 3. PHP-FPM(FastCGI)具有100个PHP进程
nginx.conf
pid /run/nginx.pid;
user www-data;
worker_processes 4;


events {
    worker_connections 1024;
}


http {
    # APACHE BACKWARDS COMPATIBILITY ENVIRONMENT VARIABLES
    map $request_uri $my_script_url {
        default $request_uri;
        ~^(?<script_filename>.+\.(php))(.*)?$ $script_filename; #/test.php or /test.php?hello=world
        ~^(?<script_filename>.*)(\?.*)$ $script_filename; #/tos?hello=world
        ~^(?<script_filename>.*)(\?.*)?$ $script_filename; #/tos or /tos/hello/world or /tos/hello/world?omg=what
    }


    # BASE SETTINGS
    charset utf-8;
    default_type application/octet-stream;
    include /etc/nginx/mime.types;
    server_tokens off;


    # CLIENT CACHING SETTINGS
    add_header Last-Modified "";
    expires 7d;


    # CONNECTION SETTINGS
    client_body_timeout 15s;
    client_header_timeout 30s;
    client_max_body_size 8m;
    keepalive_requests 10000;
    keepalive_timeout 30s;
    reset_timedout_connection on;
    resolver_timeout 5s;
    send_timeout 15s;
    tcp_nopush on;


    # FASTCGI SETTINGS
    # fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:10m max_size=1000m inactive=60m;


    # FILE CACHING AND PERFORMANCE SETTINGS
    open_file_cache max=10000 inactive=20s;
    open_file_cache_errors off;
    open_file_cache_min_uses 2;
    open_file_cache_valid 30s;
    sendfile on;


    # GZIP SETTINGS
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_types
        text/css
        text/plain
        text/javascript
        application/javascript
        application/json
        application/x-javascript
        application/xml
        application/xml+rss
        application/xhtml+xml
        application/x-font-ttf
        application/x-font-opentype
        application/vnd.ms-fontobject
        image/svg+xml
        image/x-icon
        application/rss+xml
        application/atom_xml;
    gzip_vary on;


    # LOGGING SETTINGS
    access_log /var/log/nginx/access.log combined buffer=16k;
    error_log /var/log/nginx/error.log crit;
    open_log_file_cache max=100 inactive=1m min_uses=1 valid=2m;


    # SSL SETTINGS
    # ssl_ciphers !aNULL:!eNULL:FIPS@STRENGTH;
    # ssl_prefer_server_ciphers on;
    # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # ssl_session_cache shared:SSL:10m;
    # ssl_session_timeout 3m;


    # OTHER GLOBAL CONFIGURATION FILES
    include /etc/nginx/conf.d/*.conf;


    # VIRTUAL HOST CONFIGS
    include /etc/nginx/sites-enabled/*;
}

虚拟主机配置

server {
    # BASE SETTINGS
    listen 80;
    root /var/www/tbi/example/htdocs;
    # server_name local.example.com;
    server_name www.example.com;


    # LOG SETTINGS
    access_log /var/log/nginx/www.example.com.access.log combined buffer=64k;
    error_log /var/log/nginx/www.example.com.error.log crit;


    # LOCATIONS
    location / {
        index index.php index.html;
        try_files $uri @extensionless-php;
    }

    location ~ \.(ttf|otf|eot|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }

    # location /nginx_status {
    #   See a brief synopsis of real-time, instantaneous performance
    #   stub_status on;
    # }

    location ~ \.php$ {
        expires off;

        # FASTCGI SETTINGS
        fastcgi_index index.php;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;

        # FASTCGI CACHE SETTINGS
        # fastcgi_cache microcache;
        # fastcgi_cache_bypass $http_pragma;
        # fastcgi_cache_key $scheme$host$request_uri$request_method;
        # fastcgi_cache_methods GET HEAD;
        # fastcgi_cache_use_stale updating error timeout invalid_header http_500;
        # fastcgi_cache_valid any 1m;
        # fastcgi_ignore_headers "Cache-Control" "Expires" "Set-Cookie";

        # TBI ENVIRONMENT VARIABLES
        fastcgi_param TBI_CONFIG /var/www/tbi/configs/;
        fastcgi_param TBI_DOMAIN example.com;
        # fastcgi_param TBI_ENV local;
        fastcgi_param TBI_ENV www;
        fastcgi_param TBI_RELEASETIME 0;

        # APACHE BACKWARDS COMPATIBILITY ENVIRONMENT VARIABLES
        fastcgi_param SCRIPT_URI $scheme://$http_host$my_script_url;
        fastcgi_param SCRIPT_URL $my_script_url;
    }

    location @extensionless-php {
        if (-f $request_filename.php) {
            rewrite ^/(.*)$ /$1.php last;
        }
        rewrite ^/(.*)$ /index.php?$1 last;
    }
}

非常感谢您的帮助,我需要一些关于如何使Nginx更快的建议。如果可能的话,我想避免对内核和TCP/IP进行调整。


1
去 http://serverfault.com 上询问。 - David Jashi
我还没有查看配置文件,但我猜测你的Apache MPM允许启动更多的PHP实例,而你在nginx php-fpm池中允许的实例数比这个要少,因此你有更多的并发容量。 - Chris Heald
这里肯定是OT。虽然你应该在serverfault上提问,但你真的应该多做一些工作:Siege是否在单独的机器上运行?带宽是否充足?是否使用静态内容获得了相同的结果?测试期间系统负载发生了什么?(根据我的经验,在低负载下,Apache的prefork性能不会比nginx差,但对于静态内容,nginx往往会更快,但mod_php比php-fpm更快) - symcbean
1
属于服务器故障排除(在关闭对话框中没有选择该选项) - symcbean
为什么你期望Nginx比Apache表现更好?每个场景都是不同的,如果Apache比Nginx表现更好,那你为什么要使用Nginx呢?有很多静态文件吗? - EdgeCaseBerg
显示剩余3条评论
2个回答

4

在Apache和nginx之间,PHP的性能应该是相当类似的,因为PHP是一个比服务器使用更高的瓶颈。

在你的情况下,当并发=1或并发=10时,性能看起来是相同的,只有当并发为100时,在nginx/PHP-FPM上才会变慢。

尽管您可能认为并行运行更多的PHP-FPM进程不会对许多并发查询产生更快的性能。在某一点之后,PHP并不会从并行运行中获得很大的好处。在某个点之后,更多的进程并行可以降低总吞吐量,因为它需要进行额外的上下文切换、更多的I/O访问随机争用、更高的内存使用等。

在我的测试中,就PHP-FPM进程而言,最佳表现是在6到10个之间(我使用8个)。即使在测试数百个并发连接时,这也可以为我提供最高的性能。在此之后添加更多的PHP-FPM进程会使其变慢。您的情况可能有所不同,但是100在任何服务器上都不太可能是最佳选择。

请注意,您的PHP-FPM进程数量不必等于或大于您支持的并发连接数。更好地解释一下 - 拥有8个PHP-FPM进程不意味着您只能支持8个并发连接。只要您在PHP-FPM中的listen.backlog足够高,您的服务器(nginx)仍将维护许多数百个并发连接,但是PHP-FPM将在内部仅处理它们中的8个,而不是一次性处理所有连接。这意味着每个单独的查询实际上花费的时间都会更少地由PHP执行,因为它与较少的其他进程竞争。连接仍将同时保持打开状态,并且测试数百个并发用户仍将看到所有请求快速成功地完成。

请注意,我还发现了另一种加速我的nginx设置上的PHP的方法,那就是增加fastcgi_buffers的数量/大小。我的当前设置为fastcgi_buffers 32 16k;


是的,这应该是我的第一个猜测。在四核CPU上同时运行100个高负载进程可能不是最优的选择。由于您可能有8个逻辑核心,因此8个php-fpm进程可能刚刚好。 - DougW
我的测试是使用8个PHP-FPM进程在一台只有768MB RAM和单核的廉价虚拟机上进行的,所以你的情况可能会有所不同。我认为I/O争用可能比虚拟/实际核心数量更重要,以确定多少个PHP进程是最佳选择。我鼓励任何人都去做实际测试并查看结果。 - thomasrutter
好的观点。CPU与IO的使用情况很大程度上取决于这100个进程实际在做什么。 - DougW

3

您在nginx中启用了即时gzip压缩-这是一项非常昂贵的操作,因此您有什么期待?更糟糕的是,您配置了第5级压缩,使它变得更慢,慢得要死。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接