注册

刚咬了一口馒头,服务器突然炸了!

首先,这个项目是完全使用Websocket开发,后端采用了基于Swoole开发的Hyperf框架,集成了Webscoket服务。
其次,这个项目是我们组第一次尝试使用Socket替换传统的HTTP API请求,前端使用了Vue3,前端同学定义了一套Socket管理器。


看着群里一群“小可爱”疯狂乱叫,我被吵的头都炸了,赶紧尝试定位问题。

  1. 查看是否存在Jenkins发版 -> 无
  2. 查看最新提交记录 -> 最后一次提交是下午,到晚上这段时间系统一直是稳定的
  3. 查看服务器资源,htop后,发现三台相关的云服务器资源都出现闲置状态
  4. 查看PolarDB后,既MySQL,连接池正常、吞吐量和锁正常
  5. 查看Redis,资源正常,无异常key
  6. 查看前端控制台,出现一些报错,但是这些报错经常会变化
  7. 查看前端测试环境、后端测试环境,程序全部正常
  8. 重启前端服务、后端服务、NGINX服务,好像没用,过了5分钟后,咦,好像可以访问了

就在我们组里的“小可爱”通知系统恢复正常后,20分钟不到,再一次处于无法打开的状态,沃焯!!!
完蛋了,找不出问题在哪里了,实在想不通问题究竟出在哪里。


我不服啊,我不理解啊!


咦,Nginx?对呀,我瞅瞅访问日志,于是我浏览了一下access.log,看起来貌似没什么问题,不过存在大量不同浏览器的访问记录,刷的非常快。


再瞅瞅error.log,好像哪里不太对

2023/04/20 23:15:35 [alert] 3348512#3348512: 768 worker_connections are not enough
2023/04/20 23:33:33 [alert] 3349854#3349854: *3492 open socket #735 left in connection 1013

这是什么?貌似是连接池问题,赶紧打开nginx.conf看一下配置

events {
worker_connections 666;
# multi_accept on;
}

???


运维小可爱,你特么在跟我开玩笑?虽然我们这个系统是给B端用的,还是我们自己组的不到100人,但是这连接池给的也太少了吧!


另外,前端为什么会开到 1000 个 WS 连接呢?后端为什么没有释放掉FD呢?


询问后,才知道,前端的Socket管理器,会在连接超时或者其它异常情况下,重新开启一个WS连接。


后端的心跳配置给了300秒

Constant::OPTION_OPEN_WEBSOCKET_PROTOCOL => true, // websocket 协议
Constant::OPTION_HEARTBEAT_CHECK_INTERVAL => 150,
Constant::OPTION_HEARTBEAT_IDLE_TIME => 300,

此时修改nginx.conf的配置,直接拉满!!!

worker_connections 655350;

重启Nginx,哇绰,好像可以访问了,但是每当解决一个问题,总会产生新的问题。


此时error.log中出现了新的报错:

2023/04/20 23:23:41 [crit] 3349767#3349767: accept4() failed (24: Too many open files)

这种就不怕了,貌似和Linux的文件句柄限制有关系,印象中是1024个。
至少有方向去排查,不是吗?而且这已经算是常规问题了,我只需小小的百度一下,哼哼~


拉满拉满!!

worker_rlimit_nofile 65535;

此时再次重启Nginx服务,系统恢复稳定,查看当前连接数:

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 打印结果
TIME_WAIT 1175

FIN_WAIT1 52

SYN_RECV 1

FIN_WAIT2 9

ESTABLISHED 2033

经过多次查看,发现TIME_WAITESTABLISHED都在不断减少,最后完全降下来。


本次问题排查结束,问题得到了解决,但是关于socket的连接池管理器,仍然需要优化,及时释放socket无用的连接。


作者:兰陵笑笑生666
链接:https://juejin.cn/post/7224314619865923621
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册