共计 1460 个字符,预计需要花费 4 分钟才能阅读完成。
2022.11.07 号下班路上突然收到许多用户反馈,说小程序进不去了。然后自己试了一下,打开一直转圈,于是快马加鞭赶回家,打开了电脑。
基本情况
- 文件收集小程序:帮助用户更加方便的收集各种类型的文件,同时上传之后的文件可以在线预览。
- 服务器为腾讯云 2 核 4G6M 的轻量云,同时还运行着其它的一些服务。
- 主要消耗的是上行带宽,下行主要消耗来自于文件在线预览,这部分通过内网反代理,由另外一台低配服务器负责。
问题排查
打开电脑,尝试连接 SSH,连接时间比正常情况下要多不少。等待的过程中同时登录腾讯云后台,排查之后发现情况如下:
- 内存占用 30% 多,CPU 负载正常,磁盘读写正常。
- 腾讯云后台下行带宽正常,上行一直处于峰值。
按理说照这个情况服务器应该游刃有余,然后通过腾讯云服务器日志的历史记录和小程序后台数据比对,发现变化:
- TCP 连接数 10s 内 400+,比往日多 2 倍多,CPU 负载波动幅度较大。
- 小程序的实时访问次数达 10w+,比往日同期最高都多了 1 倍多。
通过负载看不出大的问题,继续排查。
1.php-fpm 进程数
通过 Top 命令发现 php-fpm 进程比平时多了很多,大概数了一下有 70 多个,达到设置的上限 150 个还差不少。
# top #查看进程运行情况
# ........
2.TCP 连接数
ss 命令用来显示处于活动状态的套接字信息,看了一下跟腾讯云显示的差不多
$ s -ss #套接字信息
$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print(a,S[a])}' #百度找的
....
3.Nginx 允许连接数
顺带检查了一下,TCP 连接数 10s 才 400 多,Ngixn 上限设置的 5w 多 …
# worker_connections 51200;
4.mysql 连接数
show status like 'Threads%'; // 查看连接数
show processlist;// 查看连接数
总数 40 多个,大部分处于空闲休眠,活跃的也没几个。顺带看了一下设置的连接数上限,450,够用😂。
5.mysql 慢日志
打开 mysq 慢日志,设置 5s 上限,等待了一会,一条也没有。
6.php 错误日志
PHP 新产生的运行错误日志不少,大部分是 SSL 握手失败,想了想唯一请求的外部接口好像只有小程序服务端的接口,人家大厂不至于是他们的问题,问题在我这。
打开调试模式,自己模拟请求登录接口,等待了 10 多秒才有反应,然后多请求几次,最后程序报错,问题定位到一个 IP 归属地识别接口(高德高精度 IP 地址接口),请求它的时候一直超时,SSL 握手失败。
于是乎,直接删除这个 IP 地址识别这个功能,再次打开小程序流畅了不少。
7.Nginx 分析
# 筛选出 Nginx 的进程 Pid
ps -ef|grep nginx
# 查看 Nginx 进程打开的文件列表
lsof -p
原因分析
当日访问用户 7000+,由于小程序的登录状态没有本地保存,所以每次打开的时候都会重新请求登录,进而请求 IP 地址识别接口。
高德的接口有频率限制,和次数上限,然后可能触发了人家的防御机制,导致服务器 IP 被封禁了。然后所有新的登录请求全部被卡住,导致小程序访问卡死。
待改进
后续删除了 IP 地址识别功能的代码,细想其实本身也没有使用的必要。
小程序一开始没想过会有这么多用户,所以没上 Redis,经过这件事,看来还是有抽空改进的必要。
小程序使用的数据库有几十万的完全无用的数据(上传记录),可以进行归档,只保留最近的一些新数据。
事后调查
经过用户的反馈,当日峰值来自于某学校 11.07 下午 6 点后搞的活动,2500 多人,用到了这个小程序。