问题概述
在某段时间段,网站出现nginx 502,通过宝塔查看,负载状态是100%,查看监控,磁盘IO飙高,如下为近7日IO磁盘图:
排查数据
nginx抛出502,证明是它的反向代理出错,这个代理php-cgi出了问题,我用的是php-fpm,出了问题。 查看php-fpm 日志,发现并没有什么异常,提示需要提升start_servers是因为在这个时候我reload了php-fpm, 但是reload后并没作用。然后重启了nginx,才恢复了正常。
查看nginx 日志,出现了很多*12359859 connect() to unix:/tmp/php-cgi-72.sock failed (11: Resource temporarily unavailable) while connecting to upstream
根据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,其他监控内容无太大的异常
2、RDS数据库
2.1、-网络流量
2.2、RDS数据库-CPU使用率
2.3、RDS数据库-TPS/QPS
2.4、RDS数据库-慢日志
最后选择
用户请求飙升,平台又没有做什么活动,查看了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 初稿
参考
本作品采用CC BY-NC-ND 4.0进行许可。转载,请注明原作者 chunpat 及本文源链接。