线上问题排查记录

背景

在新的部门维护着一个原离职同事交接的一个API服务程序,提供给其他部门调用。API的调用频率大概在一分钟几十次。今天中午,群里反馈接口响应非常慢,经常会超时。

分析

登录上服务器看一眼日志,发现大量的错误日志

1
http: Accept error: accept tcp [::]:80: accept4: too many open files; retrying in 1s

提示很明确,打开文件数被限制了。

1
2
ulimit -n  #查询系统文件打开数量限制
1024 # 返回结果

命令查看文件打开数限制,发现是默认设置,对于服务器来说是根本不够的。
修改方式如下:

1
2
3
4
5
6
7
8
9
10
11
# 系统
echo 'fs.file-max = 65535' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# 用户
sudo tee -a /etc/security/limits.conf << EOF
lEOF

# Systemd
sudo sed -i '/DefaultLimitNOFILE/c DefaultLimitNOFILE=65535' /etc/systemd/*.conf
sudo systemctl daemon-reexec

完成后,重启服务程序。发现问题仍然没有解决。文件数限制倒是没有了,但是API的响应仍然很慢。查看Socket连接数

1
2
ps aux | grep ${proc_name} #拿到进程pid
ls -l /proc/{pid}/fd | wc -l #查看此进程下文件描述符的数量,基本可以理解为Socket的连接数

发现有大量的未断开连接。看来事情没有这么简单。只好接着去捞程序的日志了。经过一番筛查,所有的接口中,只有一个的执行有问题,对每个函数的执行时间进行分析,最终定位到了问题函数,打开源码逐行分析,发现是一个SQL查询出了问题,好吧,慢SQL…

之所以这个问题在平时没有暴露出来,是因为平时的请求量非常低,数据库的空间也足够,所以每次查询,大不了性能差点,但是不至于出问题,但是今天因为请求量高了一些,导致数据库首先撑不住了。问题解决起来也简单,直接针对关键字段添加索引,重启,一切OK了。