服务器运行情况及线上排查问题常用命令

部分内容来自转载,转载地址:https://blog.51cto.com/u_16213694/7153728

一、top命令

top

1.1 输出说明

在这里插入图片描述
输出可以分为以下两部分

1.1.1 系统概览

以下是几个需要注意的参数

  • load average
    系统负载,即任务队列的平均长度。三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。
    这里具体需要关注的还是load average三个数值。先来说说定义吧:在一段时间内,CPU正在处理以及等待CPU处理的进程数之和。三个数字分别代表了1分钟,5分钟,15分钟的统计值,这个数值的确能反应服务器的负载情况。但是,这个数值高了也并不能直接代表这台机器的性能有问题,可能是因为正在进行CPU密集型的计算,也有可能是因为I/O问题导致运行队列堵了。所以,当我们看到这个数值飙升的时候,还得具体问题具体分析。
    大家都知道,一个CPU在一个时间片里面只能运行一个进程,CPU核数的多少直接影响到这台机器在同时间能运行的进程数。所以一般来说Load Average的数值别超过这台机器的总核数,就基本没啥问题。
    CPU 100% 不是坏事,说明程序写的好把资源都利用上了,但是负载排上 10 肯定浑身难受,说明你的任务积压处理不动了。
  • swap.used
    内存信息和swap信息,所有程序的运行都是在内存中进行的,所以内存的性能对与服务器来说非常重要。不过当内存的free变少的时候,其实我们并不需要太紧张。真正需要看的是Swap中的used信息。
    Swap分区是由硬盘提供的交换区,当物理内存不够用的时候,操作系统才会把暂时不用的数据放到Swap中。所以当这个数值变高的时候,说明内存是真的不够用了。
  • cpu
    cpu利用率的计算公式
CPU%= 1 - idleTime / sysTime * 100
idleTime:CPU空闲的时间
sysTime:CPU处于用户态和内核态的时间总和
1.1.2 进程详情

以下是几个奇怪名称的含义:
NI nice值,负值表示高优先级,正值表示低优先级
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR 共享内存大小,单位kb
S 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
TIME+ 进程使用的CPU时间总计,单位1/100秒
COMMAND 命令名/命令行

1.2 常用参数

1.2.1 进程资源占用情况
top -p 28820 -p 38830   #每隔3秒显示pid是28820和pid是38830的两个进程的资源占用情况
1.2.2 查看进程下所有线程
top -Hp 31951 以线程模式查看下进程31951的所有线程情况
  • 输出

    pid是线程id。假设想看下第二个线程31998的情况,31998是操作系统的线程ID,先转成16进制,值为7cfe。
    获取该线程的信息(匹配7cf3后取20行差不多)
jstack 31951 | grep 7cfe -A 20

二、arthas工具

官网 https://arthas.aliyun.com/doc/

2.1 常用命令

  • 启动arthas
java -jar arthas-boot.jar
  • 查看某一方法实时调用 参数及返回
watch cn.chendd.blog.admin.blog.tag.controller.TagManageController queryTagsPage
  • 线程总览
dashboard
  • 打印栈,会打印线程 ID 1 的栈
thread 1
  • 查看线上代码,通过 jad 来反编译 Class
jad demo.MathGame
  • 替换运行的类
retransform /tmp/Test.class

三、jstack命令

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈。

jstack [ option ] pid

3.1 输出解读

参考https://blog.csdn.net/iteye_5603/article/details/82652200

3.1.1 关键字
locked <地址> 目标:使用synchronized申请对象锁成功,监视器的拥有者。

Blocked:线程阻塞
Waiting for monitor entry:该线程获取锁时发现锁已被持有,进入 "Entry Set"中等待
Waiting on monitor entry:该线程获取锁时发现锁已被持有,进入 "Entry Set"中等待
waiting to lock <地址> 目标:使用synchronized申请对象锁未成功,在冲入区等待。 即是 Entry Set
parking to wait for <地址> 目标

in Object.wait():获取锁后又执行obj.wait()放弃锁,在 "Wait Set"中等待的线程
Waiting on condition:等待某个资源或条件发生来唤醒自己。具体需要结合jstacktrace来分析,比如线程正在sleep,网络读写繁忙而等待
waiting on <地址> 目标:使用synchronized申请对象锁成功后,释放锁(object.wait)并在等待区等待。即是 Wait Set

Deadlock:表示有死锁

在这里插入图片描述

3.1.2 几种线程资源堵塞的情况
  • 进入队列阻塞
    线程状态BLOCKED,线程动作wait on monitor entry(第一行),调用修饰waiting to lock总是一起出现。表示在代码级别已经存在冲突的调用。
"d&a-3588" daemon waiting for monitor entry [0x000000006e5d5000]  
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()
- waiting to lock <0x0000000602f38e90> (a java.lang.Object)
at com.jiuqi.dna.bap.authority.service.UserService$LoginHandler.handle()
  • 同步块阻塞
"blocker" runnable
java.lang.Thread.State: RUNNABLE
at com.jiuqi.hcl.javadump.Blocker$1.run(Blocker.java:23)
- locked <0x00000000eb8eff68> (a java.lang.Object)
"blockee-11" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
"blockee-86" waiting for monitor entry
java.lang.Thread.State: BLOCKED (on object monitor)
at com.jiuqi.hcl.javadump.Blocker$2.run(Blocker.java:41)
- waiting to lock <0x00000000eb8eff68> (a java.lang.Object)
  • 持续运行的IO
    IO操作是可以以RUNNABLE状态达成阻塞。例如:数据库死锁、网络读写。 格外注意对IO线程的真实状态的分析。 一般来说,被捕捉到RUNNABLE的IO调用,都是有问题的。
    以下堆栈显示: 线程状态为RUNNABLE。 调用栈在SocketInputStream或SocketImpl上,socketRead0等方法。 调用栈包含了jdbc相关的包。很可能发生了数据库死锁。
"d&a-614" daemon prio=6 tid=0x0000000022f1f000 nid=0x37c8 runnable
[0x0000000027cbd000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at oracle.net.ns.Packet.receive(Packet.java:240)
at oracle.net.ns.DataPacket.receive(DataPacket.java:92)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:172)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:117)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1034)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:588)
3.1.3 其它常见情况
  • 线程sleep
"redisson-timer-6-1" #68 prio=5 os_prio=0 tid=0x0000fffe90109800 nid=0x16c waiting on condition [0x0000fffeb60bd000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at io.netty.util.HashedWheelTimer$Worker.waitForNextTick(HashedWheelTimer.java:569)
	at io.netty.util.HashedWheelTimer$Worker.run(HashedWheelTimer.java:465)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:750)
  • 线程不在cpu时间片内,从running回到runnable状态
"Apollo-RemoteConfigLongPollService-1" #17 daemon prio=5 os_prio=0 tid=0x0000ffff8d1f0000 nid=0x137 runnable [0x0000ffff6d53a000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
	at java.net.SocketInputStream.read(SocketInputStream.java:171)
	at java.net.SocketInputStream.read(SocketInputStream.java:141)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
	at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
	- locked <0x00000000e21030c0> (a java.io.BufferedInputStream)
	at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:743)
	at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1595)
	- locked <0x00000000e2103118> (a sun.net.www.protocol.http.HttpURLConnection)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1500)
	- locked <0x00000000e2103118> (a sun.net.www.protocol.http.HttpURLConnection)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at com.ctrip.framework.apollo.util.http.HttpUtil.doGetWithSerializeFunction(HttpUtil.java:104)
	at com.ctrip.framework.apollo.util.http.HttpUtil.doGet(HttpUtil.java:69)
	at com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.doLongPollingRefresh(RemoteConfigLongPollService.java:179)
	at com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.access$100(RemoteConfigLongPollService.java:49)
	at com.ctrip.framework.apollo.internals.RemoteConfigLongPollService$2.run(RemoteConfigLongPollService.java:128)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)

3.2 参数

-F 当’jstack [-l] pid’没有响应的时候强制打印栈信息
-l 长列表. 打印关于锁的附加信息,例如属于java.util.concurrent的ownable synchronizers列表.
-m 打印java和native c/c++框架的所有栈信息. 
-h | -help打印帮助信息
pid 需要被打印配置信息的java进程id,可以用jps工具查询

3.3 说明

  1. 不同的 JAVA虚机的线程 DUMP的创建方法和文件格式是不一样的,不同的 JVM版本, dump信息也有差别。
  2. 在实际运行中,往往一次 dump的信息,还不足以确认问题。建议产生三次 dump信息,如果每次 dump都指向同一个问题,我们才确定问题的典型性。

四、jmap

功能:jmap是JDK自带的工具软件,主要用于打印指定Java进程(或核心文件、远程调试服务器)的共享对象内存映射或堆内存细节。可以使用jmap生成Heap Dump,堆Dump是反应Java堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。 一般,在内存不足、GC异常等情况下,我们就会怀疑有内存泄露。这个时候我们就可以制作堆Dump来查看具体情况。

jmap [option] [server_id@]
<no option> 如果使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。
-dump:[live,]format=b,file=<filename> 以hprof二进制格式转储Java堆到指定filename的文件中。live子选项是可选的。如果指定了live子选项,堆中只有活动的对象会被转储。想要浏览heap dump,你可以使用jhat(Java堆分析工具)读取生成的文件。
-finalizerinfo 打印等待终结的对象信息。
-heap 打印一个堆的摘要信息,包括使用的GC算法、堆配置信息和generation wise heap usage。
-histo[:live] 打印堆的柱状图。其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个’*’前缀。如果指定了live子选项,则只计算活动的对象。
-permstat 打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印.
-F 强制模式。如果指定的pid没有响应,请使用jmap -dump或jmap -histo选项。此模式下,不支持live子选项。
-h 打印帮助信息。
-help 打印帮助信息。
-J<flag> 指定传递给运行jmap的JVM的参数。
-heap 打印一个堆的摘要信息 包括使用的GC算法、堆配置信息和generation wise heap usage。
C:\Users\Think>jmap -heap 10444
Attaching to process ID 10444, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b14

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0 /对应jvm启动参数-XX:MinHeapFreeRatio设置JVM堆最小空闲比率(default 40)
   MaxHeapFreeRatio         = 100 对应jvm启动参数 -XX:MaxHeapFreeRatio设置JVM堆最大空闲比率(default 70)
   MaxHeapSize              = 1258291200 (1200.0MB) //对应jvm启动参数-XX:MaxHeapSize=设置JVM堆的最大大小
   NewSize                  = 13631488 (13.0MB)/对应jvm启动参数-XX:NewSize=设置JVM堆的‘新生代’的默认大小
   MaxNewSize               = 419430400 (400.0MB)  /对应jvm启动参数-XX:MaxNewSize=设置JVM堆的‘新生代’的最大大小
   OldSize                  = 28311552 (27.0MB) //对应jvm启动参数-XX:OldSize=<value>:设置JVM堆的‘老生代’的大小
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
    //对应jvm启动参数-XX:PermSize=<value>:设置JVM堆的‘永生代’的初始大小,jdk1.8变成了元空间
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 177209344 (169.0MB)
   used     = 129068368 (123.08918762207031MB)
   free     = 48140976 (45.91081237792969MB)
   72.83383882962741% used
From Space:
   capacity = 52428800 (50.0MB)
   used     = 35522768 (33.87715148925781MB)
   free     = 16906032 (16.122848510742188MB)
   67.75430297851562% used
To Space:
   capacity = 54001664 (51.5MB)
   used     = 0 (0.0MB)
   free     = 54001664 (51.5MB)
   0.0% used
PS Old Generation
   capacity = 224395264 (214.0MB)
   used     = 141988944 (135.4112091064453MB)
   free     = 82406320 (78.58879089355469MB)
   63.27626593759127% used

90919 interned Strings occupying 16817872 bytes.

C:\Users\Think>

查看堆内存(histogram)中的对象数量及大小,应该配合过滤条件,找出占字节空间比较大的一些元素

num     #instances         #bytes  class name
编号     个数                字节     类名
----------------------------------------------
   1:             7        1322080  [I
   2:          5603         722368  <methodKlass>
   3:          5603         641944  <constMethodKlass>
   4:         34022         544352  java.lang.Integer
   5:           371         437208  <constantPoolKlass>
   6:           336         270624  <constantPoolCacheKlass>
   7:           371         253816  <instanceKlassKlass>
   后面省略
jmap -histo:live

这个命令执行,JVM会先触发gc,然后再统计信息。

输出内存使用情况到文件中,将内存使用的详细情况输出到文件,执行命令:

jmap -dump:format=b,file=heapDump 6900

然后用jhat命令可以查看dump详情,

jhat -port 5000 heapDump

在浏览器中访问:http://localhost:5000/ 查看详细信息

总结
1.如果程序内存不足或者频繁GC,很有可能存在内存泄露情况,这时候就要借助Java堆Dump查看对象的情况。
2.要制作堆Dump可以直接使用jvm自带的jmap命令
3.可以先使用jmap -heap命令查看堆的使用情况,看一下各个堆空间的占用情况。
4.使用jmap -histo:[live]查看堆内存中的对象的情况。如果有大量对象在持续被引用,并没有被释放掉,那就产生了内存泄露,就要结合代码,把不用的对象释放掉。
5.也可以使用 jmap -dump:format=b,file=命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容
6.在内存出现泄露、溢出或者其它前提条件下,建议多dump几次内存,把内存文件进行编号归档,便于后续内存整理分析。

五、jvisualvm

六、jps

jps

在这里插入图片描述
jps(Java Virtual Machine Process Status Tool)是JDK 自带的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。

七、

  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值