记一次线程爆满导致服务器崩溃的问题排查及解决
作者:阿拉的梦想 发布时间:2022-09-23 06:43:09
标签:线程,爆满,服务器,崩溃
问题介绍
测试服务器突然无法连接,ssh登录不上。只有重启才能解决。重启一天后,又连接不上了。
于是有了下面的排查过程,最终发现是有个java程序一直在创建线程,导致线程达到服务器最大数量,服务器崩溃。
1. 重启服务器
重启后,ssh连接发现下面问题
fork faild:Cannot allocate memory
以为是内存满了
于是,free -h,查看内存情况,还有,观察一段时间后,内存没多大变化
2. 修改最大线程数
经过各种百度,都说可以通过修改服务器的最大线程数来解决,于是我也这么干了。当时做的时候没有截图,所以下面截图是网上找的,凑合看看。
查看最大进程数 sysctl kernel.pid_max
ps -eLf | wc -l查看 进 程数
修改最大 进 程数后系统恢复
echo 1000000 > /proc/sys/kernel/pid_max
永久生效
echo "kernel.pid_max=1000000 " >> /etc/sysctl.conf
sysctl -p
3. 查找线程最大的java程序
上一步扩大了线程数量后,感觉有点不对,因为之前没有这么配置都可以正常运行,为什么突然服务器挂了呢?肯定是有程序在作怪。
于是决定找出占用线程最多的程序。回顾最近几天,服务器中只部署了几个springboot程序。问题一定出在它们之中。
查看线程数量前20的java程序
ps -Lef |awk ‘{sum[$2]++}END{for(pid in sum) print pid, sum[pid]}'|sort -nr -k 2|head -n 20
[root@se-test-lky01 ~]# ps -Lef |awk '{sum[$2]++}END{for(pid in sum) print pid, sum[pid]}'|sort -nr -k 2|head -n 20
16074 3100
31386 1226
20120 1072
19548 985
9697 829
3005 796
641 344
19016 324
16924 315
17870 300
6417 293
8351 171
7332 168
18259 167
19821 161
16311 157
18433 151
18048 136
14347 104
2559 100
观察一段时间后,发现进程id为16074的java程序的线程数不断增长。
4. 导出问题程序的线程日志
[root@se-test-lky01 ~]#jstack 16074 >thread_dump.log
分析日志,发现下面情况,线程数量不断增加,代码位置在FtpMonitorProcess.java:85
"Thread-4655" #4774 prio=5 os_prio=0 tid=0x00007f84aa2fe000 nid=0xd408b waiting for monitor entry [0x00007f802b704000]
java.lang.Thread.State: BLOCKED (on object monitor)
at cn.cloudwalk.bat.util.http.FtpUtil.connect(FtpUtil.java:246)
- waiting to lock <0x00000006c09c1888> (a java.lang.Class for cn.cloudwalk.bat.util.http.FtpUtil)
at cn.cloudwalk.bat.schedule.ftp.process.FtpMonitorProcess$1.run(FtpMonitorProcess.java:85)
at java.lang.Thread.run(Thread.java:748)
"Thread-4654" #4773 prio=5 os_prio=0 tid=0x00007f84aa2fc000 nid=0xd408a waiting for monitor entry [0x00007f802b805000]
java.lang.Thread.State: BLOCKED (on object monitor)
at cn.cloudwalk.bat.util.http.FtpUtil.connect(FtpUtil.java:246)
- waiting to lock <0x00000006c09c1888> (a java.lang.Class for cn.cloudwalk.bat.util.http.FtpUtil)
at cn.cloudwalk.bat.schedule.ftp.process.FtpMonitorProcess$2.run(FtpMonitorProcess.java:114)
at java.lang.Thread.run(Thread.java:748)
5. 找到问题代码
发现这个方法每次被调用就会创建一个新的线程。而这个方法是被定时任务调用的,每10秒调用一次。
问题就出在ftp没有配置,所以线程内执行ftp操作时,线程阻塞,没能释放。若ftp可用,则不会出现线程阻塞问题。
这就是问题根源。
private void listDeviceFiles() {
new Thread(new Runnable() {
@Override
public void run() {
logger.debug("开始获取[ftp-设备]文件...");
try {
String workDir = ftpConfig.getWorkdir();
// 连接
FTPClient ftpClient = FtpUtil.connect(ftpConfig);
ftpClient.changeWorkingDirectory(workDir);
ftpClient.changeWorkingDirectory(SubscribeDataTypeEnum.DEVICE_INFO.getKey().toString());
FTPFile[] files = ftpClient.listFiles();
for(FTPFile file : files) {
decomposeFile(file,ftpClient);
}
ftpClient.logout();
} catch (Exception e) {
logger.error("ftp获取文件名出错:" + e.getMessage());
}
}
}).start();
}
6. 解决方案
不建议手动创建线程,改用使用线程池。
来源:https://blog.csdn.net/A434534658/article/details/109893009


猜你喜欢
- 第一次是接触Lambda表达式是在TypeScript中(JavaScript的超集中),当时是为了让TypeScript的this方法外而
- 源代码版本 : spring-webmvc-5.1.4.RELEASE概述PathMatcher是Spring的一个概念模型接口,该接口抽象
- 背景在Java中一个回调的操作是一个在一些操作完成之后被传递到另一个函数中并且被执行的函数。一个回调函数既可以被同步或者异步执行。在一个同步
- AlertDialog的几种用法xml代码:<?xml version="1.0" encoding="
- 先来看一段魔法吧public class Test { private static void changeStr
- 1.java后台(1)使用BigDecimal类方式一:String str=new BigDecimal(num+""
- 前言身在孤岛有很多无奈,比如说程序员属于比较偏门的职业。尤其是早些年,在行业里跳过几次槽后,可能你就已经认识整个圈子的人了。然后,再跳槽很可
- 1.替换符的使用(1)在 app-android-defaultConfig (或者多渠道打包)下面可以这样使用android { &nbs
- 本文实例为大家分享了Android sharedPreferences实现记住密码功能,供大家参考,具体内容如下编写界面交互代码:packa
- 运行本实例,将显示一个用户登录界面,输入用户名(hpuacm)和密码(1111)后,单击"登录"按钮,将弹出如下图所示的
- 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性
- 本文实例讲述了Android使用AudioManager修改系统音量的方法。分享给大家供大家参考,具体如下:下面介绍几个AudioManag
- 1、通过查找API文档:2、Map.Entry是一个接口,所以不能直接实例化。3、Map.entrySet( )返回的是一个collecti
- Maven工程分模块开发完成 父工程配置了 tomcat7插件,运行 run命令执行run指令时失败,报错信息如下:D:\java\JDK8
- maven导入依赖<dependencies> <dependency> &
- 什么是代理模式?代理模式:在调用处不直接调用目标类进行操作,而是调用代理类,然后通过代理类来调用目标类进行操作。在代理类调用目标类的前后可以
- 本文实例讲述了Java编程使用卡片布局管理器。分享给大家供大家参考,具体如下:运行效果:完整示例代码:package com.han;imp
- 1.首先,八种基本数据类型分别是:int、short、float、double、long、boolean、byte、char; &
- 目录一 . 前言二 . 流程梳理2.1 实例化创建2.1.1 doGetBean 入口2.1.2 doGetBean 补充节点2.1.3 A
- // 举个例子:一个网站有用户系统、商家系统、网站后台3个系统//可以分3个userType, user ,shop , system//网