Nginx和php-fpm:无法摆脱502和504错误

2022-08-30 23:47:12

我有一个ubuntu服务器和一个相当高负载的网站。服务器是:

  • 专用于nginx,使用php-fpm(没有apache),mysql位于不同的机器上
  • 具有 8 GB 内存
  • 每秒获取大约 2000 个请求。

根据命令,每个php-fpm进程消耗大约65MB的RAM:top

top command

可用内存:

admin@myserver:~$ free -m
             total       used       free     shared    buffers     cached
Mem:          7910       7156        753          0        284       2502
-/+ buffers/cache:       4369       3540
Swap:         8099          0       8099

问题

最近,我遇到了很大的性能问题。非常大的响应时间,非常多,在晚上,当负载变得很高时,90%的用户只看到“找不到服务器”而不是网站(我似乎无法重现这个)Gateway Timeouts


原木

我的Nginx错误日志充满了休眠消息:

2012/07/18 20:36:48 [error] 3451#0: *241904 upstream prematurely closed connection while reading response header from upstream, client: 178.49.30.245, server: example.net, request: request: "GET /readarticle/121430 HTTP/1.1", upstream: "fastcgi://127.0.0.1:9001", host: "example.net", referrer: "http://example.net/articles"

我尝试切换到unix套接字,但仍然得到这些错误:

2012/07/18 19:27:30 [crit] 2275#0: *12334 connect() to unix:/tmp/fastcgi.sock failed (2: No such file or directory) while connecting to upstream, client: 84.
237.189.45, server: example.net, request: "GET /readarticle/121430 HTTP/1.1", upstream: "fastcgi://unix:/tmp/fastcgi.sock:", host: "example.net", referrer: "http
://example.net/articles"

php-fpm日志充满了这些:

[18-Jul-2012 19:23:34] WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there  are 0 idle, and 75 total children

我试图将给定的参数增加到 ,但似乎仍然不够。100


配置

这是我当前的配置

php-fpm

listen = 127.0.0.1:9001
listen.backlog = 4096
pm = dynamic
pm.max_children = 130
pm.start_servers = 40
pm.min_spare_servers = 10
pm.max_spare_servers = 40
pm.max_requests = 100

恩金克斯

worker_processes  4;
worker_rlimit_nofile 8192;
worker_priority 0;
worker_cpu_affinity 0001 0010 0100 1000;

error_log  /var/log/nginx_errors.log;

events {
    multi_accept off;
    worker_connections  4096;
}


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

    access_log off;
    sendfile        on;
    keepalive_timeout  65;
    gzip  on;

    # fastcgi parameters
    fastcgi_connect_timeout 120;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 1000;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;

    client_max_body_size 128M;

    server {
        server_name example.net;
        root /var/www/example/httpdocs;
        index index.php;
        charset utf-8;
        error_log /var/www/example/nginx_error.log;

        error_page 502 504 = /gateway_timeout.html;

        # rewrite rule
        location / {
            if (!-e $request_filename) {
                rewrite ^(.*)$ /index.php?path=$1 last;
            }
        }
        location ~* \.php {
            fastcgi_pass 127.0.0.1:9001;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_script_name;
            include fastcgi_params;
        }
    }
}

如果能就如何识别问题以及我可以调整哪些参数来解决此问题,我将不胜感激。或者也许8GB的RAM对于这种负载来说还不够?


答案 1

一些问题。仍然值得用这样一个繁忙的网站修复它们。MySQL可能是目前的根本原因。但从长远来看,你需要做更多的工作。

缓存

我看到你的一个错误消息显示对php上游的get请求。对于如此高流量的网站(您提到的2000 r / s),这看起来并不好。此页面 (/readarticle/121430) 似乎是一个完全可缓存的页面。首先,您可以使用nginx来缓存此类页面。查看 fastcgi cache

GET /readarticle/121430

php-fpm

pm.max_requests = 100

该值表示在处理 100 个请求后,php-fpm master 将终止进程。php-fpm 使用该值来对抗第三方内存泄漏。您的网站非常繁忙,有2000r / s。您的最大子进程数为 130,每个子进程最多只能处理 100 个请求。这意味着在13000/2000 = 6.5秒之后,它们都将被回收。这太多了(每秒有20个进程被杀死)。您至少应该从值 1000 开始,只要您没有看到内存泄漏,就增加该数字。有人在生产中使用了 10,000 个。

nginx.conf

  • 问题 1:

        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.php?path=$1 last;
        }
    

    应替换为更有效try_files:

        try_files $uri /index.php?path=$uri;
    

保存额外的 if 位置块和正则表达式重写规则匹配。

  • 问题2:使用unix套接字将比使用ip节省更多的时间(根据我的经验,大约10-20%)。这就是为什么php-fpm使用它作为默认值。

  • 问题3:您可能有兴趣在nginx和php-fpm之间建立保持连接。nginx官方网站中给出了一个例子。


答案 2

我需要查看您的php.ini设置,我认为这与MySQL无关,因为您收到套接字错误。另外,这是在一段时间后开始发生的事情,还是在服务器重新启动时立即发生?

尝试重新启动 php5-fpm 守护程序,看看在跟踪错误日志时会发生什么。

检查你的php.ini文件,以及你所有fastcgi_params通常位于/etc/nginx/fastcgi_params。有很多例子可以说明你想要做的事情。

另外,您是否启用了apc php缓存扩展?

它会看起来像这样在你的php.ini文件,如果你在灯堆上:

extension=apc.so
....
apc.enabled=0

从命令行进行一些mysql连接负载测试并查看结果可能也不会有什么坏处。


推荐