生产问题定位-Java线程死锁排查

本文记录了一次生产环境中遇到的线程死锁问题的定位与解决过程。问题表现为服务请求长时间等待,重启后短暂恢复。通过分析可能的原因如线程过多、内存不足等,最终确定为日志文件被第三方日志库和printStackTrace()方法同时锁定导致。解决方案包括改进异常处理,统一使用slf4j进行日志记录,并探讨了使用jstack等工具进行问题排查的方法。
摘要由CSDN通过智能技术生成

后端开发 - 记一次生产问题定位

@auther 张念磊
@date 2020/7/25

问题描述

一个服务上线生产之后两天出现了三次问题

详细征兆如下:

  1. 刚出现此问题时,浏览器的一个请求发过去,开发者工具network一栏显示该请求状态一直是padding,会持续几分钟。
  2. 网关服务打印了对应的请求。
  3. 后台服务只打印了controller中的日志,没有打印service层的日志(日志级别debug,服务正常时会打印service层的日志);
  4. 通过重启服务可暂时解决该问题,不过一段时间后会复现。

可能的原因

前提:近期用户增多,有49家机构在使用该功能模块。

  1. 服务器线程爆了:该服务器一共部署了31个微服务,还有一些对外提供的的其他服务,服务的总线程数量超过计算机的最大线程数量。
  2. 服务器内存不够:服务器内存为32GB,现有未使用1GB(每个服务的运行内存设置为300M/512M/1G)。但服务日志没有爆出内存溢出异常,不能断定是该问题。
  3. 编写的代码异常导致,但异常时服务不产生日志,无法定位问题。以前也会有此问题,程序异常,后台返回的异常原因是null,可能是该服务的config配置有误,没有准确捕捉并返回异常信息。

尝试解决

  1. 减小其他服务启动时配置的内存大小,使服务器内存处于健康状态 (已使用该方法,未能解决问题)
  2. 限制每个微服务的线程数量,使其不能超过计算机的最大线程数。(经排查,服务的线程数已被限制,每个服务被限制为200,Linux系统的总线程数为13万,故排除此原因)
  3. 为服务添加合理的全局异常捕获机制。(查看该工程的启动类中的try-catch代码块,发现catch到异常后直接返回null,没有做任何处理,在此为其添加一行代码,记录捕获到的异常到日志中)
  4. 找同事协助分析。

定位到问题

log文件被锁住导致程序无响应。具体原因:应为项目中使用到了两种打印日志的方式,一是使用第三方的slf4j打印log;二是使用printStackTrace()函数打印日志

最后

此次生产问题的原因:

  1. 日志文件被锁住了。printStackTrace()函数打印日志,和使用slf4j打印日志时对日志文件资源的抢夺,导致文件被锁住;
  2. 启动类中捕获了异常但是没有打印异常

目前的解决办法:启动类中添加异常信息的打印;删除代码中使用printStackTrace()函数的地方,改为使用slf4j打印log;

可用的其他办法:添加配置,在配置中设置只允许slf4j打印日志,不允许使用printStackTrace()函数打印日志。

补充

本次排查问题用到的知识

查看系统总线程数

/proc/sys/kernel/pid_max #查系统支持的最大线程数

查看进程下的所有线程数

先用 jps -l 查看应用的PID

jps -l

查看该Pid(进程)下的线程数

ps -Lf {pid} | wc -l

管道统计

 | wc -l

解压jar包 (可查看源码)

jar -xvf test.jar

view jstack.log

3081595828752_.pic_hd

后续

这个问题算是解决了,但是我还是有几个好奇的地方:

  1. 如何定位到的问题?
  2. 定位此类问题的思路和方法?
  3. jstack命令 如何使用?

思路:

  1. 以jstack为突破点,了解一下java堆栈分析
  2. 请教同事

下一篇博客预告:

使用jstack定位问题原因

阿里巴巴的arthas是什么?如何使用它定位生产问题?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值