Java程序员可能这辈子都无法见到的史诗级线上问题——Linux系统的线程上限被干满了!

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

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

问题描述

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

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

java 复制代码
-bash-4.2# docker ps
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7fde1873b387 m=3 sigcode=18446744073709551610

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

问题原因

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

查看最大进程数
java 复制代码
sysctl -a | grep pid_max

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

系统内部进程总数

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

java 复制代码
pstree -p | wc -l

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

top查看哪个进程占用线程数目最多
java 复制代码
top

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

ps -eLf查看这个进程到底创建了多少线程
java 复制代码
ps -eLf

问题解决

暂时解决方案

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

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

java 复制代码
kill -9 5436

深入解决问题

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

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

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

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

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

这个问题的另外一种可能

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

这些问题的解决方案大概就是更改系统的线程上限,具体我就不赘述了,大家可以参考这篇文章

最后,欢迎关注微信公众号【浣熊say】

相关推荐
码农派大星。19 分钟前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu1 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s1 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子1 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王1 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
2402_857589362 小时前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
一只爱打拳的程序猿2 小时前
【Spring】更加简单的将对象存入Spring中并使用
java·后端·spring