生产环境又出现nginx502了!!

Posted by chunpat on December 26, 2019

问题概述

在某段时间段,网站出现nginx 502,通过宝塔查看,负载状态是100%,查看监控,磁盘IO飙高,如下为近7日IO磁盘图:

FilqyanVhrxGwgOxksnDlyWAnw-W

排查数据

nginx抛出502,证明是它的反向代理出错,这个代理php-cgi出了问题,我用的是php-fpm,出了问题。 查看php-fpm 日志,发现并没有什么异常,提示需要提升start_servers是因为在这个时候我reload了php-fpm, 但是reload后并没作用。然后重启了nginx,才恢复了正常。

FilqyanVhrxGwgOxksnDlyWAnw-W

查看nginx 日志,出现了很多*12359859 connect() to unix:/tmp/php-cgi-72.sock failed (11: Resource temporarily unavailable) while connecting to upstream

FilqyanVhrxGwgOxksnDlyWAnw-W

根据nginx这个提示查了相关资料,得到了3个解决方案

1、php-fpm的sock通讯方式 改为 tcp

结论:不考虑,查了相关的blog,出现了相同问题,还从tcp改为sock模式呢!!

2、用两个php-fpm sock,nginx负载均衡

2.1、复制一份配置文件,修改里边的pid sock cp /usr/local/php/etc/php-fpm.conf cp /usr/local/php/etc/php-fpm2.conf

[global]
pid = /usr/local/php/var/run/php-fpm2.pid
error_log = /usr/local/php/var/log/php-fpm2.log
log_level = notice

[www]
listen = /tmp/php-cgi2.sock

2.2、复制一个启动文件,也修改相关的信息

cp /etc/init.d/php-fpm /etc/init.d/php-fpm2

php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm2.conf
php_fpm_PID=${prefix}/var/run/php-fpm2.pid

2.3、启动 /etc/init.d/php-fpm2 start

2.4、nginx 配置文件,增加 upstream模块

upstream backend{
    server unix:/tmp/php-cgi.sock;
    server unix:/tmp/php-cgi2.sock;
}

2.5、把fastcgi_pass unix:/tmp/php-cgi.sock;改成 fastcgi_pass backend; 重新加载 /etc/init.d/nginx reload

结论:这个方法,和我直接调大php-fpm max_children差不多,不考虑。

3、php-fpm的listen.backlog默认-1改为1024或者4096,即是调大

V友:onepunch回复,整理如下

调查

nginx (客户端) 和 php-fpm (服务端) 通过 unix socket 通信,在 connet() 时,会进行类似 tcp 的三次握手, 如果 accpet queue 队列满了,server 将发送一个 ECONNREFUSED 错误信息 Connection refused 到 client。 这样 nginx 就会报这个错了,连接不上。php-fpm 的 backlog 是 accpet queue 的最大长度

查看系统内核的最大长度

cat /proc/sys/net/core/somaxconn 128

查看 php-fpm 里的配置 listen.backlog 是 4096,由于会取这 2 个的最小值, 所以是 128。

验证当时的请求:

grep '2019-12-06T16:48' bi_svc.access.log.1 | wc -l //9903

计算9903/60等于每秒请求数165,165>128 了, 请求太多了,应该是 accpet queue 满了

解决办法

vi /etc/sysctl.conf

net.core.somaxconn = 1024

将 /proc/sys/net/core/somaxconn 改成 1024 就不会出问题了

结论:这个方法是稳定PV提升、IO提升的解决方案,不过我这边遇到的是突然的提升,所以我这边不会这样子做

更多服务器信息

1、云服务器ECS

1.1、系统磁盘BPS,其他监控内容无太大的异常 FilqyanVhrxGwgOxksnDlyWAnw-W

2、RDS数据库

2.1、-网络流量 FilqyanVhrxGwgOxksnDlyWAnw-W

2.2、RDS数据库-CPU使用率 FilqyanVhrxGwgOxksnDlyWAnw-W

2.3、RDS数据库-TPS/QPS FilqyanVhrxGwgOxksnDlyWAnw-W

2.4、RDS数据库-慢日志 FilqyanVhrxGwgOxksnDlyWAnw-W

最后选择

用户请求飙升,平台又没有做什么活动,查看了nginx access log,分析同一个ip,同一时间段上百个请求同 一个访问链接,所以决定iptable限制下,控制单个IP的最大30并发连接数。

sudo iptables -I INPUT -p tcp --dport 443 -m connlimit --connlimit-above 30 -j REJECT
sudo iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j REJECT

后续

问题还是出现了,查看下一篇post

迭代

  • 2019年12月27日 15:29:00 初稿

参考


Creative Commons License
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 chunpat 及本文源链接。