502 高负载下的网关错误 (nginx/php-fpm)

2022-08-30 11:13:09

我为一个相当繁忙的互联网网站工作,该网站经常获得非常大的流量峰值。在这些峰值期间,每秒请求数百个页面,这会产生随机的 502 网关错误。

现在,我们在一台具有 4 个 SAS 15k 驱动器 (raid10) 的计算机上运行 Nginx (1.0.10) 和 PHP-FPM,该驱动器具有 16 个核心 CPU 和 24GB 的 DDR3 内存。此外,我们还使用最新的Xcache版本。DB 位于另一台计算机上,但此计算机的负载非常低,并且没有问题。

在正常负载下,一切都运行良好,系统负载低于1,PHP-FPM状态报告从未真正同时显示超过10个活动进程。始终有大约10GB的RAM仍然可用。在正常负载下,机器每秒处理大约 100 次网页浏览量。

当巨大的流量高峰到达并且每秒从机器请求数百次页面浏览量时,问题就出现了。我注意到FPM的状态报告随后显示多达50个活动进程,但这仍然远远低于我们配置的最大300个连接数。在这些峰值期间,Nginx状态报告多达5000个活动连接,而不是正常的平均值1000个。

操作系统信息:CentOS 5.7 版(最终版)

CPU: 英特尔(R) 至强(R) 处理器 E5620 @ 2.40GH (16 核)

php-fpm.conf

daemonize = yes
listen = /tmp/fpm.sock
pm = static
pm.max_children = 300
pm.max_requests = 1000

我没有设置rlimit_files,因为据我所知,如果您不这样做,它应该使用系统默认值。

fastcgi_params(仅向标准文件添加值)

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;
fastcgi_intercept_errors on;

fastcgi_pass            unix:/tmp/fpm.sock;

nginx.conf

worker_processes        8;
worker_connections      16384;
sendfile                on;
tcp_nopush              on;
keepalive_timeout       4;

Nginx通过Unix Socket连接到FPM。

sysctl.conf

net.ipv4.ip_forward = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 1
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.eth0.rp_filter=1
net.ipv4.conf.lo.rp_filter=1
net.ipv4.ip_conntrack_max = 100000

limits.conf

* soft nofile 65536
* hard nofile 65536

以下是以下命令的结果:

ulimit -n
65536

ulimit -Sn
65536

ulimit -Hn
65536

cat /proc/sys/fs/file-max
2390143

问题:如果PHP-FPM没有耗尽连接,负载仍然很低,并且有足够的RAM可用,那么在高流量期间可能导致这些随机502网关错误的瓶颈是什么?

注意:默认情况下,这台机器的ulimit是1024,因为我将其更改为65536,我还没有完全重新启动机器,因为它是一台生产机器,这意味着太多的停机时间。


答案 1

这应该可以解决它...

你有: fastcgi_buffers 4 256k;

将其更改为: fastcgi_buffers 256 16k; // 总共 4096k

同时将fastcgi_max_temp_file_size设置为 0,如果回复开始超出 fastcgi 缓冲区,则将禁用到磁盘的缓冲。


答案 2

Unix 套接字默认接受 128 个连接。把这条线放进去是件好事/etc/sysctl.conf

net.core.somaxconn = 4096

推荐