dump分析工具_Java应用CPU过高,如何排查?参考解决思路和常用工具总结

2ce58c46b0e701c7fc596b4fc89b0d66.png

本文总结了一些常见的线上应急现象和对应排查步骤和工具。分享的主要目的是想让对线上问题接触少的同学有个预先认知,免得在遇到实际问题时手忙脚乱。毕竟作者自己也是从手忙脚乱时走过来的。

只不过这里先提示一下。在线上应急过程中要记住,只有一个总体目标:尽快恢复服务,消除影响。不管处于应急的哪个阶段,我们首先必须想到的是恢复问题,恢复问题不一定能够定位问题,也不一定有完美的解决方案,也许是通过经验判断,也许是预设开关等,但都可能让我们达到快速恢复的目的,然后保留部分现场,再去定位问题、解决问题和复盘

在大多数情况下,我们都是先优先恢复服务,保留下当时的异常信息(内存dump、线程dump、gc log等等,在紧急情况下甚至可以不用保留,等到事后去复现),等到服务正常,再去复盘问题。

edcb6840e56a9784d93700795f0308da.png

常见现象:CPU 利用率高/飙升

场景预设:

监控系统突然告警,提示服务器负载异常。

预先说明:

CPU飙升只是一种现象,其中具体的问题可能有很多种,这里只是借这个现象切入。

注:CPU使用率是衡量系统繁忙程度的重要指标。但是CPU使用率的安全阈值是相对的,取决于你的系统的IO密集型还是计算密集型。一般计算密集型应用CPU使用率偏高load偏低,IO密集型相反。

常见原因:

  • 频繁 gc
  • 死循环、线程阻塞、io wait...etc

模拟

这里为了演示,用一个最简单的死循环来模拟CPU飙升的场景,下面是模拟代码,

在一个最简单的SpringBoot Web 项目中增加CpuReaper这个类,

@Componentpublic class CpuReaper {    @PostConstruct    public void cpuReaper() {        int num = 0;        long start = System.currentTimeMillis() / 1000;        while (true) {            num = num + 1;            if (num == Integer.MAX_VALUE) {                System.out.println("reset");                num = 0;            }            if ((System.currentTimeMillis() / 1000) - start > 1000) {                return;            }        }    }}

打包成jar之后,在服务器上运行。java -jar cpu-reaper.jar

(1)第一步:定位出问题的线程

方法 a: 传统的方法

1、top 定位CPU 最高的进程执行top命令,查看所有进程占系统CPU的排序,定位是哪个进程搞的鬼。在本例中就是咱们的java进程。PID那一列就是进程号。

f397ee835ac694750eb3dfe9eb705023.png

2、top -Hp pid 定位使用 CPU 最高的线程

64b8a14990eca10f3f29c2465a40494b.png

3、printf '0x%x' tid 线程 id 转化 16 进制

> printf '0x%x' 12817> 0x3211

4、jstack pid | grep tid 找到线程堆栈

> jstack 12816 | grep 0x3211 -A 30
302f16482616d24b2dfbce11a6ea1be2.png

方法 b: show-busy-java-threads

这个脚本来自于github上一个开源项目,项目提供了很多有用的脚本,show-busy-java-threads就是其中的一个。使用这个脚本,可以直接简化方法A中的繁琐步骤。如下,

> wget --no-check-certificate https://raw.github.com/oldratlee/useful-scripts/release-2.x/bin/show-busy-java-threads> chmod +x show-busy-java-threads> ./show-busy-java-threads
show-busy-java-threads# 从所有运行的Java进程中找出最消耗CPU的线程(缺省5个),打印出其线程栈# 缺省会自动从所有的Java进程中找出最消耗CPU的线程,这样用更方便# 当然你可以手动指定要分析的Java进程Id,以保证只会显示你关心的那个Java进程的信息show-busy-java-threads -p show-busy-java-threads -c 

方法 c: arthas thread

阿里开源的arthas现在已经几乎包揽了我们线上排查问题的工作,提供了一个很完整的工具集。在这个场景中,也只需要一个thread -n命令即可。

> curl -O https://arthas.gitee.io/arthas-boot.jar # 下载

后续

通过第一步,找出有问题的代码之后,观察到线程栈之后。我们就要根据具体问题来具体分析。这里举几个例子。

1、情况一:发现使用CPU最高的都是GC 线程。

GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fd99001f800 nid=0x779 runnableGC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fd990021800 nid=0x77a runnable GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007fd990023000 nid=0x77b runnable GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007fd990025000 nid=0x77c runnabl

2、情况二:发现使用CPU最高的是业务线程

  • io wait
    • 比如此例中,就是因为磁盘空间不够导致的io阻塞
  • 等待内核态锁,如 synchronized
    • jstack -l pid | grep BLOCKED 查看阻塞态线程堆栈
    • dump 线程栈,分析线程持锁情况。
    • arthas提供了thread -b,可以找出当前阻塞其他线程的线程。针对 synchronized 情况

常见现象:频繁 GC

1、 回顾GC流程

在了解下面内容之前,请先花点时间回顾一下GC的整个流程。

7bde237f84b552fc1136d389c5974a97.png

接前面的内容,这个情况下,我们自然而然想到去查看gc 的具体情况。

  • 方法a : 查看gc 日志
  • 方法b : jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计
  • 方法c : 如果所在公司有对应用进行监控的组件当然更方便(比如Prometheus + Grafana)

这里对开启 gc log 进行补充说明。一个常常被讨论的问题(惯性思维)是在生产环境中GC日志是否应该开启。因为它所产生的开销通常都非常有限,因此我的答案是需要开启。但并不一定在启动JVM时就必须指定GC日志参数。

HotSpot JVM有一类特别的参数叫做可管理的参数。对于这些参数,可以在运行时修改他们的值。我们这里所讨论的所有参数以及以“PrintGC”开头的参数都是可管理的参数。这样在任何时候我们都可以开启或是关闭GC日志。比如我们可以使用JDK自带的jinfo工具来设置这些参数,或者是通过JMX客户端调用HotSpotDiagnostic MXBean的setVMOption方法来设置这些参数。

这里再次大赞arthas❤️,它提供的vmoption命令可以直接查看,更新VM诊断相关的参数。

获取到gc日志之后,可以上传到GC easy帮助分析,得到可视化的图表分析结果。

f7903d9ac8275fb8f82251fd8292eabc.png

2、GC 原因及定位

prommotion failed

从S区晋升的对象在老年代也放不下导致 FullGC(fgc 回收无效则抛 OOM)。

可能原因:

  • survivor 区太小,对象过早进入老年代查看 SurvivorRatio 参数
  • 大对象分配,没有足够的内存dump 堆,profiler/MAT 分析对象占用情况
  • old 区存在大量对象dump 堆,profiler/MAT 分析对象占用情况

你也可以从full GC 的效果来推断问题,正常情况下,一次full GC应该会回收大量内存,所以 正常的堆内存曲线应该是呈锯齿形。如果你发现full gc 之后堆内存几乎没有下降,那么可以推断:**堆中有大量不能回收的对象且在不停膨胀,使堆的使用占比超过full GC的触发阈值,但又回收不掉,导致full GC一直执行。换句话来说,可能是内存泄露了。

一般来说,GC相关的异常推断都需要涉及到内存分析,使用jmap之类的工具dump出内存快照(或者 Arthas的heapdump)命令,然后使用MAT、JProfiler、JVisualVM等可视化内存分析工具。

至于内存分析之后的步骤,就需要小伙伴们根据具体问题具体分析啦。

六、涉及工具

再说下一些工具。

  • Arthas
  • useful-scripts
  • GC easy
  • Smart Java thread dump analyzer - thread dump analysis in seconds
  • PerfMa - Java虚拟机参数/线程dump/内存dump分析
  • Linux 命令
  • Java N 板斧
  • MAT、JProfiler...等可视化内存分析工具

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dos攻击命令_Kali Linux系列之拒绝服务攻击(DOS)实战(上)

(你的世界是个什么样的世界?你说,我们倾听!)-----------------小百科拒绝服务攻击即是攻击者想办法让目标机器停止提供服务,是黑客常用的攻击手段之一。其实对网络带宽进行的消耗性攻击只是拒绝服务攻击的一小部分,只要能够对目标…

stm32定时器配置

stm32通用定时器 STM32的定时器是个强大的模块,定时器使用的频率也是很高的,定时器可以做一些基本的定时,还可以做PWM输出或者输入捕获功能。 时钟源问题: 名为TIMx的有八个,其中TIM1和TIM8挂在APB2总线上,…

python数组定义_python定义数组

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 一、一维数组 1. 直接定义matrix2. 间接定义matrixprint(matrix)输出:3. 数组乘法matrix*5print…

Android-语言设置流程分析

Android手机语言切换行为,是通过设置-语言和输入法-语言来改变手机的语言,其实这个功能很少被用户使用。 以Android5.1工程源码为基础,从设置app入手来分析和学习语言切换的过程:一、语言设置界面:首先在设置app中找到语言设置这个Preference…

charles 安装 ssl_最全面的解决Charles手机抓包的证书问题(步骤非常详细)

源自公众号文章: 彻底解决Charles手机抓包的证书问题简介: Charles 抓包是日常开发当中经常会用到的技术, 在 Android 6 之前, 手机系统既信任系统内置的证书, 也信任用户自己安装的证书, 但是在 Android 7 之后, 却发生了变化, 手机系统只信任系统内置的根证书. 当然了, 这是为…

excel 2007 vba与宏完全剖析_Excel宏VBA小技巧系列 | 分段加合

写在前面的话 知识产权算是一个盛产数据的行业。专利啊商标啊著作啊,都有著录项目。我们常说的专利分析、产业导航、企业导航、产业预警、竞争情报、技术综述、知识产权评议等等,常规操作之一就要先处理著录项目数据,然后再进行不同角度的分…

redhat虚拟机安装

做过好多使用VMware workstation虚拟机搭建的系统,这是我第一次使用Virtual Box,感觉跟Vmware差不多,我的本子的系统是win7 64位。 下面演示安装的是在VirtualBox里安装rhel 6.4 linux 64位系统。 一、VirtualBOX 版本。 二、虚拟机的配置。…

mysql 查看表v空间自增涨_MySQL InnoDB表空间加密

从 MySQL5.7.11开始,MySQL对InnoDB支持存储在单独表空间中的表的数据加密 。此功能为物理表空间数据文件提供静态加密。该加密是在引擎内部数据页级别的加密手段,在数据页写入文件系统时加密,加密用的是AES算法,而其解密是在从文件…

ideaspringboot项目上传服务器_PHP中使用 TUS 协议来实现可恢复文件上传

曾经尝试过用PHP上传大文件吗?想知道您是否可以从上次中断的地方继续上传,而不会在遇到任何中断的情况下再次重新上传整个数据?如果您觉得这个场景很熟悉,请接着往下阅读。文件上传是我们几乎所有现代Web项目中的一项很常见的任务…

java使用xml存储数据_用存储过程和 JAVA 写报表数据源有什么弊端?

用存储过程和 JAVA 写报表数据源有什么弊端?跟着小编一起来一看一下吧!我们在报表开发中经常会使用存储过程准备数据,存储过程支持分步计算,可以实现非常复杂的计算逻辑,为报表开发带来便利。所以,报表开发…

MAC OS上JAVA1.6 升级1.7,以及 maven3.2.1配置

一、我的MAC系统 预装的Jdk是1.6,由于需要使用eclipse MARs 2版本,故需要升级到1.7 二、下载JAVA jdk http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html 不知道为什么直接下非常慢,后来用的迅雷就超级快…

sql server 创建唯一性非聚集索引语句_数据库专题—索引原理

深入浅出数据库索引原理参见:https://www.cnblogs.com/aspwebchh/p/6652855.html1.为什么给表加上主键?1.平时创建表的时候,都会给表加上主键。如果没有主键的表,数据会一行行的排列在磁盘上,查找一个数据需要一条条的进行对比。而…

oracle数据库更新语句_20_手把手教你学Python之操作数据库

数据库是数据的仓库,将大量数据按照一定的方式组织并存储起来,方便进行管理和维护,例如快速检索和统计等。数据库的主要特点:以一定的方式组织、存储数据;能为多个用户共享;与程序彼此独立。……数据库管理…

查询Oracle正在执行的sql语句

--查询Oracle正在执行的sql语句及执行该语句的用户 [sql] view plaincopy SELECT b.sid oracleID, b.username 登录Oracle用户名, b.serial#, spid 操作系统ID, paddr, sql_text 正在执行的SQL, b.machine 计算机名 FROM v$p…

WinForm 清空界面控件值的小技巧

WinForm 清空界面控件值的小技巧 原文:WinForm 清空界面控件值的小技巧在WinForm里面有时候需要清空自己输入内容或是选择的选项,以便重新操作流程,那么一般你是怎么清空界面各个控件值的呢?如果窗体里面控件,尤其是TextBox控件比…

virsh的使用

2019独角兽企业重金招聘Python工程师标准>>> ###这里最先要完成的是对网卡的配置(os ubuntu14.04) 目的是实现vm上是以桥接的方式联网 修改/etc/network/interfaces # interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback #auto eth0…

SQL Server - 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)

因为篇幅原因,AlwaysOn可用性组被拆成了两部分:理论部分和实战部分。而实战部分又被拆成了准备工作和AlwaysOn可用性组搭建。 三篇文章各自的链接: SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn&…

python 3.6.5编译安装_Linux系统安装Python3.6.5

Linux系统安装Python3.6.5 1、下载Python3.6.5 wget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz 如果报command not found则执行:yum -y install wget命令后再进行下载 也可下载好安装包进行手动上传 2、安装Python3.6可能使用的依赖 yum install o…

从传统运维到云运维演进历程之软件定义存储(一)

运维是企业业务系统从规划、设计、实施、交付到运维的最后一个步骤,也是重要的步骤。运维从横向、纵向分可以分为多个维度和层次,本文试图抛开这纷繁复杂的概念,讲述一个传统的企业级运维人员转型到云运维人员,尤其是软件定义存储…

Abp Uow 设计

初始化入口 在AbpKernelModule类中&#xff0c;通过UnitOfWorkRegistrar.Initialize(IocManager) 方法去初始化 1 /// <summary>2 /// This class is used to register interceptor for needed classes for Unit Of Work mechanism.3 /// </summary>4 …