程序员很难见到的史诗级问题:Linux系统的线程上限被干满了!

面试七股多一股 2024-03-07 07:40:24

先简单描述下这次线上问题的原因和处理,大概就是另外一个同事发现配置nginx的时候,docker指令没办法用了,一用就会报错pthread_create failed,有点儿linux基础的都知道,这是创建新线程失败了。

但是,我就很好奇,什么样的情况下会把linux系统的线程上限给干满?最开始我怀疑的是这台服务器的线程上限设置得太小了,导致被干满了,但是随着我逐渐深入的查问题原因,我发现里面隐藏着一些不可告诉人的秘密——坨巨大的shit在我们项目里面。

问题描述

同时在修改了些nginx配置,重启docker的时候,告诉我出现了一个线程上问题,具体如下:

我立马登陆上服务器,用docker ps试了一下,果然这个服务的docker都用不了了,报错如下:

-bash-4.2# docker psruntime/cgo: pthread_create failed: Resource temporarily unavailableSIGABRT: abortPC=0x7fde1873b387 m=3 sigcode=18446744073709551610

很显然,是docker ps的命令core了,core的具体原因是告诉我linux系统级别的函数pthread_create创建线程失败了,具体原因是资源不足。

问题原因

当然!遇到这种问题我肯定是不慌的,不就是线程上限达到了吗?肯定是线程上限设置得过小,让我们来查看一下Linux服务器的线程上限,命令如下:

查看最大进程数sysctl -a | grep pid_max

这不看不要紧,一看吓一跳,系统的线程上限设置是没有问题的,65536个线程数目,这是一般Linux系统的线程上限设置,所有问题都指向了一个可怕的结论,那就是有进程把最大线程数干满了。

系统内部进程总数

没办法,接着查查看系统内部的进程总数,一看接着吓一跳,线程数目来到了65040个,几乎干满了65535个线程的上限。

pstree -p | wc -l

这个结果说明是系统线程被耗尽了,肯定代码有问题,线程资源没有释放。

top查看哪个进程占用线程数目最多top

最后通过top这个命令发现pid = 5346的进程线程数异常的高,我怀疑是5436这个进程对应的服务有问题,线程创建完了之后没有被释放。

ps -eLf查看这个进程到底创建了多少线程ps -eLf问题解决暂时解决方案

终于通过排查定位了问题是pid=5436这个服务中的代码有异常,创建的线程资源没有被及时的释放,导致整个linux服务器的最大线程数都被占满了。

为了暂时先解决这个问题,保障线上正常访问,我选择了先重启该服务,重启之后线程得到了释放,随即docker也恢复了正常。

kill -9 5436深入解决问题

这个问题的本质还是业务层面代码有问题,应该是什么地方的线程资源没有释放,导致最后占满了整个系统的线程资源。

后续我排查了项目代码,发现是IOT推送模块儿导致的,之前的老哥的websock没有采用netty之类的三方库,而是自己手动撸了一个websock的注册和推送逻辑。

而这部分的前端开发会频繁的去页面创建新的websock连接,每个websock连接在Java后台都会去new一个新的线程,然而前端完事儿之后没有释放websock连接,后台的推送模块儿也没有检测失效websock连接并关闭的逻辑。

这就导致最近前端在更改代码之后,干爆了后台Linux服务器的线程创建上限,我真的是一个大写的服!

后续解决的话是websock的推送模块儿全部改成使用netty的websock进行推送,所以这个故事告诉我们不要轻易的自己造轮子!

这个问题的另外一种可能

在网上搜索了这个错误,发现其它人也遇到了同样的错误,但是他们的错误大多数是由于系统线程上限设置较低造成的,而不是由于我这种服务线程把系统线程干满了。

0 阅读:0