配置 Nginx + PHP-FPM 以实现高流量负载

配置 Nginx + PHP-FPM 以实现高流量负载

我的 nginx 一直崩溃,并在浏览器中报告“坏网关”错误。Nginx 和 PHP-FPM 未预先配置为处理大量流量负载。我不得不systemctl restart php7.0-fpm每小时设置一个 cron 作业,以确保我的网站在崩溃时不会停机太久。让我们开始吧。

我收到一些错误/var/log/php7.0-fpm.log

[20-Sep-2017 12:08:21] NOTICE: [pool web3] child 3495 started
[20-Sep-2017 12:08:21] NOTICE: [pool web3] child 2642 exited with code 0 after 499.814492 seconds from start

[20-Sep-2017 12:32:28] WARNING: [pool web3] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 8 children, there are 7 idle, and 57 total children

nginx 日志中没有任何内容。如果我让它运行太长时间而不重新启动它(PHP-FPM),我将收到网关错误。我已经尝试按照教程调整设置 3 次,但仍然没有用。现在我的所有设置可能都偏离了方向,但无论我怎么做,它都不起作用。

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;

worker_rlimit_nofile 100000;

events {
        worker_connections 4096;
        use epoll;
        multi_accept on;
}


http {
        sendfile on;
        reset_timedout_connection on;
        client_body_timeout 10;
        send_timeout 2;
        keepalive_timeout 30;
        keepalive_requests 100000;
        tcp_nopush on;
        tcp_nodelay on;
        types_hash_max_size 2048;
        fastcgi_read_timeout 300000;
        client_max_body_size 9000m;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
        open_file_cache max=200000 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;

        access_log off;
}

/etc/php/7.0/fpm/php-fpm.conf

    [www]

    pm = dynamic
    pm.max_spare_servers = 200
    pm.min_spare_servers = 100
    pm.start_servers = 100
    pm.max_children = 300

    [global]
    pid = /run/php/php7.0-fpm.pid
    error_log = /var/log/php7.0-fpm.log
    include=/etc/php/7.0/fpm/pool.d/*.conf

/etc/php/7.0/fpm/pool.d/www.conf

[www]

user = www-data
group = www-data
listen = /run/php/php7.0-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 300
pm.start_servers = 100
pm.min_spare_servers = 100
pm.max_spare_servers = 200
pm.max_requests = 500

我的一个网站(/etc/php/7.0/fpm/pool.d/web3.conf):

[web3]

listen = /var/lib/php7.0-fpm/web3.sock
listen.owner = web3
listen.group = www-data
listen.mode = 0660

user = web3
group = client1

pm = dynamic
pm.max_children = 141
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 500

chdir = /

env[HOSTNAME] = $HOSTNAME
env[TMP] = /var/www/clients/client1/web3/tmp
env[TMPDIR] = /var/www/clients/client1/web3/tmp
env[TEMP] = /var/www/clients/client1/web3/tmp
env[PATH] = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

htop 中的资源/进程使用情况:

在此处输入图片描述

答案1

问题出在您的数据库访问上。您有多个 MySQL 进程使用 CPU,这表明数据库查询需要很长时间才能执行。

您需要仔细检查您的申请,寻找以下内容:

  1. 数据库查询已适当优化。
  2. 数据库设计高效,并且有适当的索引。
  3. 应用程序具有适当的数据缓存。

缓慢的数据库查询会导致 PHP-FPM 用尽处理客户端请求的可用子进程。这将导致502 Bad Gateway错误。您可以尝试增加池pm.max_children的设置web3,因为这会导致错误。这可以消除可扩展性症状,但不能解决应用程序/数据库效率低下的根本原因。

如果您不使用该www池,您可以将其删除以节省其使用的资源。

理想的设置pm.max_requests是零,也就是说,PHP 工作程序永远不应重新启动。如果您的 PHP 工作程序不会因库的编码不当而泄漏内存,那么您可以使用零。否则,您可以使用任何值来保持工作程序的内存使用量合理。关于此设置,真的没有其他好的建议。

这里你无法对 nginx 设置做太多改动,因为 PHP-FPM 有时不可用。你可以更改gzip_comp_level1,这会让 nginx 花费更少的 CPU 来压缩输出。但与应用程序优化相比,这效果真的很小。

答案2

(这应该是一条评论,但是有点长)

我的网站经常崩溃

....这不是容量问题,除非您的服务器配置太差,导致 oom killer 启动。而且这不是您从日志中引用的错误。

为什么在一个具有 12 GB RAM 的盒子上会有半 GB 的交换空间?

你的 keepalive 太高了。

您已禁用访问日志记录(您的日志开始寻找容量问题的地方)。

上面的输出暗示了 mysql 性能存在问题。

您的 pm.max_requests 太低。

您尚未限制 listen_backlog。

您在此处向我们展示的所有内容都有问题,而这只是冰山一角。投票结束

答案3

是 web3 网站要下线了吗?这个日志条目似乎暗示了原因:

[20-Sep-2017 12:32:28] WARNING: [pool web3] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)

对于 www 站点,start_servers / max_spare_servers 的值确实很高,但对于 web3 ,其值却低得多。

您似乎没有内存不足,因此为 mysql 提供更多内存可能会有所帮助。除非您的 php 应用程序从不查询 mysql,否则将 mysql 排除在优化过程之外是一个错误。

首先,您需要查看 mysql 配置。我相信大多数发行版在内存设置和线程数量方面都相当保守。查找 mysql 示例配置,例如:my-large.cnf my-medium.cnf 并将它们与您的配置进行比较。基于 Debian 的发行版将它们放在 /usr/share/doc/mysql-server-xy/examples/ 中(其中 xy 是主要版本)

调整各种旋钮时,我建议进行小幅调整。例如,将值从 8M 更改为 16M。

如果这是您的 php 应用程序,您还需要查看慢查询日志,如 Tero Kilkanen 的回答所建议的那样。

希望有所帮助。

答案4

htop 似乎表明与 MySQL 相关的 15 个 PID 中的每一个都使用了超过 1:nn.nn 的 TIME,并且每个都使用了至少 1G 的 VIRT RAM。由于您总共有 12 GB 的 RAM,是时候与我们分享您的

SHOW GLOBAL STATUS;
SHOW GLOBAL VARIABLES;
SHOW ENGINE INNODB STATUS;

允许对 MySQL 配置进行一些合理的检查,即使这不是问题?正常运行时间为 1 天 11 小时,令人鼓舞。

知道 PID 6148 正在做什么吗?它已经投入了 28:+ 的时间?

来自今天早些时候@xendi 的回复......“每当发生这种情况时,所有网站上的所有页面,无论什么脚本或内容,都会因网关错误而出错。这发生在所有页面和网站上”
您是否认为 php.ini session.gc_maxlifetime = nnnn 垃圾收集秒数可能是原因?

2017 年 9 月 24 日 可能产生影响的 nginx.conf 问题

client_max_body_size 9000m;    # really 9G in one body?
client_body_timeout 10;   # seconds to receive the client body seems short.
open_file_cache max=200000 inactive=20s;   may be causing churn at 20s

https://www.linode.com/docs/web-servers/nginx/configure-nginx-for-optimized-performance/     

可能是有用的链接。

相关内容