问题描述: 线上 node 服务在压力测试高并发的时候, 3 分钟后请求逐渐失败, 查看服务器日志发现 Error: spawn find EMFILE 错误, 进而导致 node 进程 crash 并不再重启.
解决问题与复盘:
通过查询服务端 checklist, EMFILE 错误是由于 unix 服务器打开文件过多导致系统触发安全机制抛出错误.
通过全面审视后端业务逻辑, 发现并没有打开文件的相关逻辑, 从而定位网络 I/O socket 是问题所在. 根据 unix 哲学一切皆文件, socket 是以一种特殊的文件形式存在系统中的,
但是通常业务逻辑是不会使用太多的 socket 的, 第一 TCP 中的 socket 会尽可能复用, 第二 mysql 连接池一般也只会用到 255 个链接, 第三即使在优化 redis 客户端链接后
仍然未解决问题, 所以定位在服务器的调优方向上.
ulimit
ulimit 值是服务器调优的一个方面, 它限定了服务器允许当前 shell 打开的进程能够打开的 socket 数量, 我们可以通过 ulimit -a 来查看 open file 的数量.
一般来说, 1024 是足够的, 但是面对高并发业务, 1024 是不足的, 通常需要调高, 至于调多高需要视业务需求而定.
所以通过上调 ulimit 的 s(soft) 与 h(hard) 值可以达到调优效果, 但是在实际中发现, 线上服务器的 ulimit 值已经达到 100 w 以上.
通过对比开发环境与线上环境, 定位问题出现在 docker 容器. docker 容器继承了宿主机的内核, 但是偏偏不继承宿主机的 ulimit 值, 所以查看 docker 容器的 ulimit 值发现只有
4096, 通过上调 docker 容器的 ulimit 值, 再次压测, 没有报错并且 node 进程不会 crash. 问题解决.
解决方法: 上调系统(docker 容器, 宿主机)的 ulimit 值达到服务器调优效果.
【php高并发502,记一次 node 服务高并发 502 错误】PS: 线上环境极其复杂, 必须要熟悉业务的人员才能更快速地定位问题.(大厂的 bug 果然不一样)