Spring Boot假死诊断实战记录
作者:大名Dean鼎 发布时间:2022-02-11 17:03:38
这两天遇到一个服务假死的问题,具体现象就是服务不再接收任何请求,客户端会抛出Broken Pipe。
检查系统状态
执行top,发现CPU和内存占用都不高,但是通过命令
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
发现有大量的CLOSE_WAIT端口占用,继续调用该服务的api,等待超时之后发现CLOSE_WAIT的数量也没有上升,也就是说服务几乎完全僵死。
检查JVM情况
怀疑可能是线程有死锁,决定先dump一下线程情况,执行
jstack <pid> > /tmp/thread.hump
发现tomcat线程基本也正常,都是parking状态。
这就比较奇怪了,继续想是不是GC导致了STW,使用jstat查看垃圾回收情况
app@server:/tmp$ jstat -gcutil 1 2000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 27.79 65.01 15.30 94.75 92.23 1338 44.375 1881 475.064 519.439
一看吓一跳,FGC的次数居然超过了YGC,时长有475s。一定是有什么原因触发了FGC,好在我们打开了GC log。
发现一段时间内频繁发生Allocation Failure引起的Full GC。而且eden区的使用占比也很大,考虑有频繁新建对象逃逸到老年代造成问题。询问了一下业务的开发,确认有一个外部对接API没有分页,查询后可能会产生大量对象。
由于外部API暂时无法联系对方修改,所以为了先解决问题,对原有的MaxNewSize进扩容,从192MB扩容到一倍。经过几天的观察,发现gc基本趋于正常
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 3.37 60.55 8.60 95.08 92.98 87 2.421 0 0.000 2.421
扩容之前对heap进行了dump
jmap -dump:format=b,file=heapDump <PID>
通过MAT分析内存泄露,居然疑似是jdbc中的一个类,但其实整体占用堆容量并不多。
分析了线程数量,大约是240多条,与正常时也并没有很大的出入。而且大量的是在sleep的定时线程。
总结
本次排查其实并未找到真正的原因,间接表象是FGC频繁导致服务假死。而且acturator端口是正常工作的,导致health check进程误认为服务正常,没有触发告警。如果你也遇到类似的情况欢迎一起讨论。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。
来源:http://www.deanwangpro.com/2019/07/28/zombie-thread-trouble-shooting/
猜你喜欢
- Maven工程分模块开发完成 父工程配置了 tomcat7插件,运行 run命令执行run指令时失败,报错信息如下:D:\java\JDK8
- RunnableRunnable接口非常简单,就定义了一个方法run(), 实现Runnable接口的run方法就可以实现多线程// 函数式
- springboot + docker + jenkins自动化部署项目,jenkins、mysql、redis都是docker运行的,并且
- 前言近期一直在忙项目,我也是打工仔。不多说,我们开始玩一玩seata。什么都不说,我们按照惯例,先上一个图(图里不规范的使用请忽略):简单一
- Mybatis-Plus是一个优秀的Mybatis增强工具,目前更新到3.1.1。Mybatis-Plus原生提供了很多单表操作的方法,极大
- 本文主要介绍了面向对象的三大特征实例解析,下面看看具体内容。封装封装一个Teacher和Student类package com.hz.tes
- // 十进制转化为十六进制,结果为C8。 Integer.toHexString(200); //十六进制转化为十进制,
- 问题描述在开发批量删除功能时,往往都是多条数据,所以前台需要传一个数组给后台,但是怎么在URL中绑定一个数组,同时在后台用@PathVari
- 在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进
- 1,添加依赖在project的build.gradle文件中添加dependencies { classpath 'co
- 表单的重复提交: 没有完整的进行一次,先请求表单页面->再提交表单过程而完成数据提交造成的根本原因: 没有完整的进行一次,先请求表单页
- 一、系统介绍1.开发环境开发工具:Eclipse2021JDK版本:jdk1.8Mysql版本:8.0.132.技术选型Java+Swing
- 分享一个在项目中用的到文件上传下载和对图片的压缩,直接从项目中扒出来的:)package com.eabax.plugin.yundada.
- 命令行编译java文件import java.util.*;public class shuchu{ public
- 问题由来一个简单的需求,要求把和当前用户相关的数据置顶展示。这里,我用了一个简单的用户表来复现这个需求。很简单,查询语句后面加上:order
- 在 Java 中将 Object 转换为 Int我们可以使用 Object 类来引用我们在 Java 中不知道其类型的任
- 这两种方式也是大家在日常编码工作当中用的比较多的判断方式、之前在使用的时候也没太关注两者在比较不同类型的时候存在哪些区别今天就和大家一起深入
- @RequestMapping注解注意点类上加没加@RequestMappin注解区别1.如果类上加了 @RequestMappin注解,那
- GlobalLock的作用对于某条数据进行更新操作,如果全局事务正在进行,当某个本地事务需要更新该数据时,需要使用@GlobalLock确保
- 1. 开方:Math.sqrt(x);2. x的a方:Math.pow(x,a);3. 绝对值:Math.abs(x);4. BigInte