线上问题排查实战
1,线上CPU突然升高
1.1 使用top命令
查看当前机器的cpu占比,进入top后,输入大写的P,进程按照CPU从高到底排序
1.2 使用 top -Hp PID
使用 top -Hp pid 查看当前进程下的所有线程使用cpu情况
前面的pid为当前线程号
1.3 将线程号转十六进制
使用 printf '%x\n' 线程号
看到当前线程转换后是7f7e,在该线程号前加上0x后0x7f7e就是jstack命令下的nid的
1.4 jstack查看线程号定位问题
jstack 17038 | grep '0x4295' -C10 --color
发现最耗CPU的线程是GC线程,继续使用jmap命令看当前进程的堆内存使用情况
jmap -heap pid
1.5 查看GC频率
查看gc频率的命令(其中O代表老年代占用率,FGC是FullGC次数,FGCT是fullGC时间;可以看出在频繁FullGC但是老年代有资源一直释放不掉)
其中17038为进程号,5000是指每5秒(5000毫秒)输出一次
jstat -gcutil 17038 5000
1.6 通过分析出问题时线上日志发现内存溢出;至此定位到问题根源是内存溢出导致(有未释放资源堆积,导致老年代被占满,然后频繁的FullGC但是资源一直释放不了)
2 造成原因
2.1 内存消耗过大,导致FullGC次数过多
造成FullGC原因:
- 生成大量的对象,导致内存溢出-使用工具分析对象 查看具体内存对象占用情况。
- 内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。
2.2 代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢
在1.4中可以定位到具体的线程和代码,是否是复杂算法或者无限循环导致
2.3 由于锁使用不当,导致死锁。
如果有死锁,在1.4 中会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。
2.4 随机出现大量线程访问接口缓慢。
代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。
思路:
首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点
2.5 某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;
执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架