JAVA-Linux系统常用诊断工具

当用于运行情况、响应情况异常时,会直接表现为系统的指标异常,而指标需要通过相关的系统指令来获取。

项目中遇到一些问题的时候总是不知道该怎么查,怎么解决,没有好记性就文字记录一下。

Linux下常用诊断工具

uptime

快速查看服务器的负载情况

返回系统的平均负荷,包括1min, 5min, 15min内可以运行的任务平均数,包括正在运行的任务以及虽然可以运行但正在等待某个处理器空闲的任务。

如果1min平均负载很高,而15min的平均负载很低,说明服务器正在面临高负载情况,需要进一步排查CPU资源都消耗在哪里。
如果1min平均负载很低,而15min的平均负载很高,则有可能CPU资源紧张时刻已经过去了。

dmesg | tail

输出系统日志的最后10行。常见的OOM kill 和 TCP丢包在这里都会有记录

vmstat 1

实时性能检测工具,可以展现给定时间间隔服务器的状态值,包括服务器的CPU使用率、内存使用、虚拟机内存交换情况、I/O读写情况等系统核心指标。(每隔一秒显示一行)
一般主要关注输出的CPU使用情况,其中id + us + sy = 100,
id : 是空闲CPU使用率
us : 是用户CPU使用率
sy : 是系统CPU使用率
如果用户时间和系统时间相加非常大(us+sy),说明cpu正忙于执行指令。
如果I/O等待时间很长,那么系统的瓶颈可能在磁盘I/O

CPU空闲可能的原因:

  • 应用被同步原语阻塞,直至所释放才能继续执行
  • 应用在等待某些东西,例如数据库调用所返回的响应
  • 应用的确是无所事事

在计算cpu使用率的时候,建议多获取几次,尤其是在脚本里获取时。建议在脚本里获取两次以上并排除第一次的数据

mpstat -P ALL 1

显示每个cpu的使用情况。
如果一个cpu占用率特别高,说明可能是一个单线程应用程序引起的

free -m

可以查看系统内存的使用情况,-m参数表示按照兆字节展示。
如果可用内存非常少,系统可能会动用交换区(swap),这时会增加I/O开销(iostat命令中体现)
需要注意的是,返回信息的第一行是针对整个系统来说的,因此Buffer和Cache都被计算在了used里,其实这两部分内存可以被很快拿来供应用程序使用的。
真正反映内存使用情况的是第二行。

sar -n DEV 1

sar命令主要是用来查看网络设备的吞吐率。
可以通过 网络设备的吞吐率判断网络设备是否已经饱和

top

包含了系统全局的很多指标信息。
包括系统负载情况、系统内存使用情况、系统 cpu使用情况等,基本涵盖了上述几条命令的功能。
可以相对全面地查看系统负载的来源。
top命令支持排序,可以按照不同列排序,方便地找出诸如内存占用最多的进程、cpu占用率最高的进程等。

注意 top是一个瞬时输出的值,最好通过定时存储其值到文件中来进行比对诊断。

JDK常用诊断工具

全在JAVA_HOME/bin下

性能分析

在系统层面能够影响应用性能的一般包括三个因素:CPU、内存、I/O。可以从这三方面进行程序的性能瓶颈分析

cpu分析

第一步: 使用top, vmstat, ps等命令查看系统cpu使用率是否有异常,从而判断出是否是cpu繁忙造成的性能问题。
主要通过us(用户进程所占的百分比)来看异常的进程信息。当us接近100% 甚至更高时,可以确定是cpu繁忙造成的响应缓慢。
一般来说,cpu繁忙的原因主要有:

  1. 线程中有无线空循环、无阻塞、正则匹配或单纯的计算
  2. 发生了频繁GC – jstat -gcutil [pid] 判断是否是GC造成的cpu繁忙
  3. 多线程的上下文切换 – vmstat 1 5 【看cs次数】,判断是否是上下文切换造成的cpu繁忙
    确定cpu使用率最高的进程之后可以使用jstack 来打印异常进程的堆栈信息

第二步: jstack [pid]

jstack 只能打印进程的信息,包含此进程下所有线程(轻量级进程 LWP)的堆栈信息。
如果需要进一步确定是哪一个线程耗费了到了cpu资源,可以使用

top -p [processId] -H

查看 或者 通过

ps -Le
来显示所有进程,包括LWP的资源耗费信息。
最后通过jstack的输出文件中查找对应的 LWP的十六进制ID(printf %0x [processId]),即可定位到相应的堆栈信息。

需要注意线程的状态是RUNNABLE,WAITING等。对于RUNNABLE的进程需要注意的是否有耗费cpu资源的计算,对于WAITING的线程一般是所得等待操作。

jstack查看线程栈时需要注意:JVM只能在Safepoint转储出一个线程的栈
jstack dump实现机制每次只能转储出一个线程的栈信息,因此输出信息中可能会看到一些冲突信息,如一个线程正在等待的锁并没有被其他线程持有,多个线程持有同一个锁等。

有时候可能会由JIT引起一些cpu飚高,如大量方法编译等,可以使用 -XX:+PrintCompilation参数输出JIT编译情况,来排查JIT编译引发的cpu问题

内存分析

对于Java应用来说,内存主要有堆外内存和堆内内存组成

堆外内存

主要是JNI、Deflater/Inflater、DirectByteBuffer(NIO中会用到)使用的。
对于堆外内存的分析,主要通过 vmstat、sar、top、pidstat等命令查看Swap和物理内存的消耗情况在做判断。
对于JNI、Deflater这种调用可以通过Google-preftools来追踪资源使用情况

堆內内存

是java应用主要的内存区域。与这部分内存性能相关的主要有

  1. 创建对象:一般存储在堆中,需要控制好对象的 数量和大小,尤其是大对象容易进入老年代
  2. 全局集合:全局集合通常生命周期比较长,因此需要特别注意全局集合的使用
  3. 缓存:缓存选用的数据结构不同,会很大程度上影响内存的大小和GC
  4. ClassLoader:主要是动态加载类容易造成永久代内存不足
  5. 多线程:线程分配会占用本地内存,过多线程会造成内存不足

以上使用不当就容易造成
频繁GC –> Sope the world,会使应用响应变慢
OOM, 直接造成内存溢出错误使程序退出
OOM分为:
Heap space: 堆内存不足
PerGen space: 永久代内存不足
Native thread: 本地线程没有足够内存可分配

排查堆内存问题常用工具是JDK自带的 jmap

查看JVM内存使用情况:
jmp -heap

查看JVM内存存活的对象
jmap -histo:live

把heap里所有对象都dump下来,不论对象是死是活
jmap -dump:format=b,file=xxx.hprof

先做一次Full GC, 在dump,只包含仍然存活的对象信息
jmap -dump:format=b,live,file=xxx.hprof

另外, Eclipse的MAT(Memory Analyzer Tool)可以看到具体的堆栈和内存中对象的信息。
JDK自带的jhat 也能够查看dump文件,并启动web端口供浏览器浏览

I/O分析

通常与应用性能相关的I/O分析包括文件I/O和网络I/O

文件I/O

可以使用系统工具 pidstat、 iostat、vmstat 来查看I/O情况
vmstat 主要看bi和bo,由此可判断I/O是否繁忙
bi:设备每秒接收的块数量
bo: 设备每秒发送的块数量

可以进一步使用strace工具定位堆文件I/O的系统调用。
通常造成文件I/O性能差的原因:

  1. 大量的随机读/写
  2. 文件太大
  3. 网络I/O

查看网络I/O
一般使用netstat工具。可以查看所有连接的状况、数目、端口信息等。如TIME_WAIT或CLOSE_WAIT连接过多时,会影响应用的响应速度。
netstat -anp

还可以使用tcpdump来分析网络I/O的数据。tcpdump是一堆二进制数据,可以使用Wireshark查看具体的连接以及其中数据的内容
tcpdump -i eth0 -w tmp.cap -tnn dst post 8080 监听8080端口的网络请求并打印日志到tmp.cap

还可以通过/proc/interrupts来获取当前系统使用的中断情况
cat /proc/interrupts
展示的内容各列依次是:irq的序号,在各自cpu上发生中断的次数,可编程中断控制器,设备名称(request_list的dev_name字段)

通过查看网卡设备的终端情况可以判断网络I/O的情况。

其他分析工具

VisualVM

Java应用检测工具,原理是通过JMX接口来连接JVM进程,从而能够看到JVM上的线程、内存、类等信息。

Arthas 诊断工具,可使用profiler命令导出火焰图分析数据(待整理)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
OSZAR »