线上服务异常的定位、处理与优化的探索 - 第四章 常用分析工具介绍与使用

 常用分析工具介绍与使用

 

JVM内置指令

内置指令指的是“安装JDK后”可以直接使用的命令,在未集成可视化工具时也能进行JVM相关分析和优化。

  1. JPS

类似linux ps命令,只输出Java进程,过滤掉其他进程信息

# jps -m

# jps -l

# jps -mlv 显示非常详细的java进程信息,并带有JVM参数

 

 

  

  1. JSTAT

查看gc时的内存信息和所耗时间

# jstat -gc <pid> <间隔时间> 按KB显示

# jstat -gcutil <pid> <间隔时间> 按百分比显示

# jstat -gccapacity <pid> 堆内存统计与GC次数

 

 

 

 

  列

  表示

单位

新生代

S0C

幸存者0区总大小

KB

S1C

幸存者1区总大小

S0U

幸存者0区已使用大小

S1U

幸存者1区已使用大小

EC

Eden区总大小

EU

Eden区总已使用大小

老年代

OC

老年代总大小

OU

老年代已使用大小

永久代

PC

永久代总大小

PU

永久代已使用大小

GC

YGC

Young GC次数

YGCT

Young GC总耗时时间

FGC

Full GC次数

FGCT

Full GC总耗时时间

GCT

GC总耗时时间

  

 

 

 

  列

  表示

单位

新生代

S0

幸存者0区

百分比

S1

幸存者1区

E

Eden区

老年代

O

老年代总

永久代

P

永久代总

GC

YGC

Young GC次数

YGCT

Young GC总耗时时间

FGC

Full GC次数

FGCT

Full GC总耗时时间

GCT

GC总耗时时间

  1. JSTACK

查看线程信息,一般用来快速定位高占CPU线程。

# jstack -l <pid> 查看活动线程

# jstack -l <pid> >>[文件名] 导出活动线程信息到指定文件

# jstack <pid> | grep <’线程ID’> 查看线程信息

 

 

 

 

  1. JMAP

查看堆信息或导出堆内存快照(二进制),导出的快照文件需传回本地再使用图形界面工具详细分析。

注意:JMAP可能引起持续FULL GC,造成程序短暂无响应,应避免在线上业务高峰期操作。

# jmap -heap <pid> 查看堆信息概要

# jmap -dump:format=b,file=[文件名称].hprof <pid> 导出可分析的JVM内存快照信息

左侧图中所示JVM概要信息和堆概要信息在第三章节已详细阐述,不再赘述。

  1. JINFO

查看JVM参数信息,以及对JVM动态设置一些参数(并非所有参数都能动态设置)

# jinfo <pid> 查看JVM参数设置的详细信息

# jinfo -flag +PrintGCDetails <pid> 动态设置JVM参数->添加GC打印日志

# jinfo -flag -PrintGCDetails <pid> 动态设置JVM参数->去掉GC打印日志

# jinfo -flag +PrintGC <pid> 动态设置JVM参数->添加GC打印日志

# jinfo -flag -PrintGC <pid> 动态设置JVM参数->去掉GC打印日志

JConsole

JConsole一个基于JMX的可视化的JVM监控、分析工具,同时提供本地监控和远程监控两种方式。使用JConsole可以清晰方便的监控、分析应用程序的堆内存、线程、死锁、CPU占用率、载入类等信息。

  • 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JConsole、远程连接进程方式。
  • 本小节中为了启动JMX远程功能,需要修改部分应用的配置文件。调优结束后切记将这些配置文件还原,避免生产环境上出现其他问题。

远程连接配置

  1. 修改jboss-as-7.2.0.Final/bin/standalone.conf配置文件

开启JMX支持,同时配置JMX所需参数

JAVA_OPTS="$JAVA_OPTS -Djava.rmi.server.hostname=192.168.3.91"

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.port=8950"

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false"

JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=org.jboss.byteman,org.jboss.logmanager -Djava.awt.headless=true"

JAVA_OPTS="$JAVA_OPTS -Djava.util.logging.manager=org.jboss.logmanager.LogManager"

JAVA_OPTS="$JAVA_OPTS -Xbootclasspath/p:$JBOSS_HOME/modules/system/layers/base/org/jboss/logmanager/main/jboss-logmanager-1.4.0.Final.jar"

 

  1. 修改jboss-as-7.2.0.Final/standalone/configuration/standalone.xml配置文件

修改Jboss日志管理器配置,避免与JMX日志管理冲突

 

  1. 启动JConsole

使用本地CMD启动连接远程Linux上的进程

# jconsole <ip>:<port>

 

提示连接失败时,请选择“不安全”方式连接(不安全指未开启SSL)。

 

功能与使用

概览界面可以直观看到当前监控的应用的堆内存、线程、载入类、CPU占用率等,所有数据均为实时加载变化。

 

内存页签中选择下拉列选查看新生代、老年代、永久代等实时堆内存信息。右下角绿色柱状图与之对应,鼠标滑过会有提示。点击右上角执行GC,会马上向JVM发出指令执行一次垃圾收集。同时左下角会累计记录GC的所耗时间,如图所示:

 

 

 

 

线程页签可以查看峰值最高活动线程以及当前活动线程。左下角记录当前存活的线程。当怀疑应用出现死锁时点击左下角按钮“检测死锁”,如果有死锁出现则会在右下方显示死锁线程的详细信息,可以准确定位死锁代码和位置。

 

 

 

 

类载入页签可以查看当前监控的JVM载入的类数量、以及卸载类的数量信息。

 

VM概要页面中可以查看当前监控的JVM参数的详细数据,相当于是对前面页签提供的数据给出一个总结

 

VisualVM

VisualVM同样也是JDK自带的一款基于JMX的可视化工具。不仅提供了类似JConsole的功能,同时可以支持一键生成堆内存快照、线程快照,并支持使用插件添加更多扩展功能,可以认为是JConsole的加强版。

  • 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JConsole、远程连接进程方式。
  • 本小节中为了启动JMX远程功能,需要修改部分应用的配置文件。调优结束后切记将这些配置文件还原,避免生产环境上出现其他问题。

远程连接配置

  • 远程连接JBOSS启用JMX配置与上一章节(JConsole)一致,这里不再赘述。

打开jdk\bin目录下的jvisualvm.exe,选中左侧菜单“远程”,单机右键添加远程主机

 

选择刚才添加的主机,右键添加JMX连接(连接信息是JBOSS中所配置的JMX参数)。

 

 

 

 

功能与使用

概述界面描述了当前连接的主机所使用的JDK信息,以及JVM设置的参数信息。

 

监视页签中实施展示CPU、堆内存、永久代、载入类、线程等信息。右侧按钮“堆Dump”支持一键生成当前堆内存快照,类似JMAP功能。

 

导出Dump文件传回本地后,可以通过主菜单中的文件>装入后做具体数据分析。

 

 

 

线程页签中可以查看当前JVM的各种线程信息,包括:运行|休眠|等待。右侧线程Dump提供一键追踪和分析线程功能。

 

 

 

 

插件安装:选择工具>插件>设置>编辑,输入插件目录的URL地址。

URL查询地址:https://visualvm.github.io/pluginscenters.html,区分JDK版本。

 

MAT

Memory Analyzer Tool简称MAT,是一款基于Eclipse的堆内存快照分析工具,具有极其强大的分析功能!同时它也是一个上手容易深入了解很复杂的工具,官方使用文档多达数百页。MAT支持导入Dump文件分析,并自动生成问题报告,方便快速找到内存泄露或线程性能等问题。MAT支持OQL查询语言(类似SQL),使用OQL可以迅速查找想要看的内存内容。

www.eclipse.org/mat下载MAT,解压后即可使用。

功能与使用

在使用MAT之前首先需要拿到堆内存快照文件,4.1章节中有详细介绍这里不再赘述。

File>Open Heap Dump打开堆内存快照。

 

选择Leak Suspects Report,自动生成内存泄露嫌疑报告。

 

Actions>Histogram:列举内存中对象存在的个数和大小

 

选择一个可疑对象,右键MergeShortestPathsToGCRoots>excludeall phantom/weak/soft etc.references

 

逐步点开分析具体的泄露对象,注意:下方有对象总数:Total。

 

回到主页,点击Report>Leak Suspects

 

泄露报告中主要关注两点:

1:饼图深色部分是MAT分析后认为的可疑泄漏点。

2:每个泄漏点分别列出Problem Suspect和Details。

 

 

 

 

Problem Suspect 2所涉及到system class loader是类加载器正常执行现象,故排除。

Problem Suspect 1>See stacktrace查看线程堆栈跟踪分析

 

 

 

 

根据线程的追踪信息可以分析到内存泄露的具体代码的位置。

 

更多

关于MAT的功能和用法只做了简单的介绍,MAT是一个上手容易,深入了解很复杂的工具,使用MAT排查问题需要极强的耐心一步一步点下去深入分析。更多MAT功能请查阅官方文档深入了解:www.eclipse.org/mat/documentation

JProfiler

JProfiler是一款功能强大的性能采集剖析工具,提供可视化的操作界面,通常与性能压测类软件配合使用,也支持本地和远程服务端的连接方式。提供对SQL语句、线程、内存泄露、CPU使用率、执行类、执行方法等的监控和性能瓶颈的采集分析。

远程连接配置

  • 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、JProfiler11、远程连接进程方式。
  • 本小节中为了启动JProfiler远程功能,需要修改JBoss容器的启动脚本。使用结束后切记将启动文件还原,避免生产环境上出现其他问题。
  • 远程连接成功的前提时需要本地端和远程端都安装同一大版本号的JProfile,否则会提示版本不一致无法连接。Linux下解压JProfile即可,无需添加环境变量。

正式调试之前我们首先需要使用JProfile的session功能为应用服务器启动脚本添加启动参数。Session>Integration Wizards>New Server Integration

 

 选择容器以及版本(涵盖目前所有主流容器)

 

 

选择服务器操作系统以及处理器架构方式

 

选择JVM厂商:Oracle、IBM、J9……

选择JVM版本: 指服务器端的JVM版本

选择JDK所使用的虚拟机:如何查看所使用的虚拟机:java -version,下一步

 

 

 

 

选择连接方式,这里选择跟随容器服务立即启动监听,下一步

 

输入服务器上JProfile的安装路径,下一步

 

默认即可,下一步

 

这一步需要先将容器的启动脚本下载到本地,选择启动脚本,下一步

 

填写一个访问端口,缺省8849,下一步

 

选择稍后启动即可。至此,远程连接的配置部分结束了。在第8步配置时我们选择了一个启动脚本,同时JProfile也为我们生成了一个全新的启动脚本:standalone_jprofiler.sh

编辑此脚本,确保JProfile参数的位置在standalone.conf配置下方,否则JVM将采用默认的永久代参数启动脚本,导致堆内存溢出PermGen Space。

改前:

 

 

 

改后:

 

最后将standalone_jprofiler.sh上传到JBoss启动脚本目录下,使用该脚本启动应用即可。

功能与使用

Session>Start Center,选择上一步所配置的连接

 

选择Sampling(Recommended)采样模式,下一步默认即可。

 

首页Overview视图展示了内存、GC、加载Class数、线程、CPU使用率等实时监控信息,还可以通过左侧菜单选择子视图查看具体分类信息的实时采集数据。

 

CPU views是一个比较常用的性能分析功能,此视图展示了应用中各方法的执行次数、执行时间、调用关系等信息,对定位和分析应用性能有绝佳的帮助。

CPU views>Call Tree通过树形图清晰地展现了方法间的层次调用关系。同时按照方法的执行总时间由大到小排序,简明清晰的展示所有服务端的请求。

 

CPU views>Hot Spots视图展示方法的单独执行时间、总执行时间、平均执行时间、调用次数等。

 

CPU views>Call Graph,选定Hot Spots视图中方法后右键选择Show Call Graph展示出与该方法直接关联的所有方法的关系图。

 

Databases同样是一个比较常用的性能分析功能,一般用来分析SQL执行的慢查询。

Databases>JDBC>Connections视图显示当前JDBC连接数量。

 

Databases>JDBC>Hot Spots视图展示了当前所采集到的SQL语句以及执行消耗的时间。

 

选定一条SQL,右键Show Node Details,可以查看该SQL的具体内容。

 

更多

  • 官网地址下载:https://www.ej-technologies.com/download/jprofiler/files。
  • 官方帮助文档:https://www.ej-technologies.com/resources/jprofiler/help/doc/main/introduction.html#jprofiler.introduction

Arthas

Arthas是Alibaba开源的Java诊断工具,采用命令行的交互模式使用,具有极其强大的线上服务诊断、监控、热部署功能,被广泛应用于IT企业。

安装与启动

安装Arthas

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

安装命令执行后,会在当前位置下载Arthas程序

启动Arthas

# java -jar arthas-boot.jar 直接启动

# java -jar arthas-boot.jar --target-ip 192.168.3.91 绑定IP形式支持web console形式访问,默认端口8563.

启动之后自动加载所有java进程,输入进程编号后真正进入工作模式(挂在到相应的进程上)

 

常用命令

类别

命令

解释

基础

stop

停止并退出Arthas

cls

清屏

keymap

快捷键列表

高阶

dashborad

查看当前系统的实时数据面板

thread

查看当前线程信息

vmoption

查看、更新JVM诊断相关的参数

jad

反编译指定已加载类的源码

watch

方法执行数据的观察:入参、返回值、异常等

redefine

用于替换Class(热更新)

trace

观察方法内部调用路径,以及方法路径上的每个节点上耗时

ognl

用于执行ognl表达式

tt

作用类似于watch命令,watch是一次性的,tt能够保存下来,方便后续持续分析,重新调用,还原当时的情况等

profiler

生成应用热点的火焰图

使用详解

  • 示例基于JBoss-7.2.0、CentOS7.4、E7-FSSC、JDK1.7、Arthas3.2.0。
  • 本小节中为了介绍Arthas常用命令如何使用启动了Arthas,生产环境下使用结束后一定记得关闭Arthas进程,一是避免过多资源消耗,二是Art。
  • 仅选取使用频次较高的命令讲解。

dashboard命令可以查看当前系统的实时数据面板

ID: 线程ID,这个ID不是jstack中的ID,此ID用于Arthas的thread命令使用

NAME: 线程名

GROUP: 线程组名

PRIORITY: 线程优先级1~10之间,数字越大表示优先级越高

STATE: 线程的状态

CPU%: 线程消耗的cpu占比,采样100ms

TIME: 线程运行总时间,数据格式为{分:秒}

DAEMON: 是否是daemon线程

 

thread命令可以查看线程的信息和堆栈数据

thread 显示所有线程的信息

thread id 显示指定线程ID的堆栈信息(此ID为dashboard中的id)

thread -b 找出当前阻塞其他线程的线程

thread -n N 当前最忙的前N个线程并打印堆栈

thread --state <状态> 查看指定状态的线程(NEW/RUNNABLE/BLOCKED/WAITING/TIMED_WAITING/TERMINATED)

 

vmoption 命令可以查看、更新JVM诊断相关的参数(并非所有JVM参数都支持热更新)

vmoption 显示JVM参数和状态

vmoption PrintGCDetails true 更新指定参数的值(示例命令为开启GC详细日志)

 

jad 命令可以反编译指定已加载类的源码,通常用于查看源码是否存在打包未更新,以及与redefine一起用于热更新操作

jad com.epoch.customizeproject.xx.utils.XxUtil 反编译类

jad com.epoch.customizeproject.xx.utils.XxUtil callExecuteSql 反编译指定函数

 

watch 命令用于方法执行数据的观察:入参、返回值、异常等

watch <类名表达式> <方法名表达式> <观察表达式> <条件表达式>

watch com.xx.xx methodXX “{params,returnObj}” -x 3 (“”中间的都是ognl表达式)

-x 指定输出结果的属性遍历深度,默认为 1

-b 在方法调用之前观察

-s 在方法返回之后观察

-e 在方法异常之后观察

-f 在方法结束之后(正常返回和异常返回)观察

-E 开启正则表达式匹配,默认为通配符匹配

 

redefine 命令用于替换Class(热更新),一般结合jad、mc等命令使用

redefine /usr/app/LoginAction.class(修改后的Class文件位置)

redefine 后的Class不能使用reset还原

redefine 后的Class,再使用watch/jad/trace/tt/等命令会将修改后的字节码重置

redefine 的Class不能增加field/method,只能修改现有函数,同时正在运行的函数需等到执行完毕才能替换成功

 

trace 命令用于观察方法内部调用路径,以及方法路径上的每个节点上耗时

trace com.xx.xx methodXX 捕获指定类指定方法的调用路径

trace com.xx.xx methodXX '#cost > 100' 在调用路径中只捕获执行时间超过100ms的结果

trace -E com.xx.ClassA|com.xx.ClassB method1|method2|method3支持正则表达式,可以同时监控多个类的多个方法的调用路径

 

 

 

ognl 命令用于执行ognl表达式:loader/clazz/method/target/params/returnObj/throwExp/isBefore/isThrow/isReturn

ognl的特殊用法请参考:https://github.com/alibaba/arthas/issues/71

ognl的表达式官方指南:https://commons.apache.org/proper/commons-ognl/language-guide.html

tt 命令作用类似于watch命令,watch是一次性的,tt能够保存下来,方便后续持续分析,重新调用,还原当时的情况等。

tt -t com.xx.xx methodXX 记录调用

tt -t com.xx.xx methodXX -n 5 记录调用5次后即退出命令(避免JVM内存撑爆)

tt -l 展示所有捕获的记录

tt -s 'method.name=="methodXX"' 从记录中筛选出方法名为methodXX的记录

tt -i index 查看指定编号的调用信息,index是tt列表中的编号

tt -i index -x 2 同上,所记录的参数向下展开2层明细信息

tt -i index -p 通过所记录的调用信息,重新调用一次,相当于还原当时的情况

tt命令是将当前环境的对象引用保存起来,如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值,此情况请移步watch实时命令跟踪。

 

profiler 命令用于生成应用热点的火焰图。

profiler start 启动采集数据

profiler getSamples 获取已采集的sample的数量

profiler status 查看采集状态

profiler stop 停止采集数据

profiler stop --file /usr/app/arthas/20200502-2257.svg 指定火焰图保存目录

profiler stop --format html 指定生成火焰图格式

通过web console->Arthas Output可以直接打开已经生成的火焰图文件,图中信息支持下钻。

 

 

 

 

 

更多

  • 如果条件允许建议尽量避开应用的高峰期使用Arthas排查问题,Arthas有可能拖慢应用速度(一些的监控、加载、观测、录制命令等)。
  • 章节4.6.3未详尽所有Arthas命令,更多命令与教程请查阅官方文档:https://arthas.gitee.io/index.html
  • 一张图掌握Arthas命令:https://gitee.com/arthas/arthas/issues/I180P1
  • 用户案例:https://github.com/alibaba/arthas/issues?q=label%3Auser-case
posted @ 2022-12-05 20:12  江湖危险快点跑  阅读(167)  评论(0编辑  收藏  举报