对于线上系统突然产生的运行缓慢问题,1000查看

2019-10-07 07:51 来源:未知
3.1、使用jstat -gcutil命令查看进程的内部存款和储蓄器情形
[ylp@ylp-web-01 ~]$ jstat -gcutil 14063 2000 10 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 0.00 100.00 99.99 26.31 42 21.917 218 1484.830 1506.747 0.00 0.00 100.00 99.99 26.31 42 21.917 218 1484.830 1506.747 0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484 0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484 0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484 0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484 0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484 0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355 0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355 0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355

从出口消息方可知见,Eden区内部存款和储蓄器占用百分之百,Old区内部存款和储蓄器占用99.99%,Full GC的次数高达2二十遍,並且频繁Full GC,Full GC的持续时间也特意长,平均每一回Full GC耗时6.8秒(1505.439/220)。依据这几个音信,基本可以明确是程序代码上出现了难点,只怕存在不客观创设对象的地点

java.lang.Thread.State: RUNNABLE

轻巧看见存在死循环。

2.3、查看难点线程客栈

挑选TID为14065的线程,查看该线程的库房意况,先将线程id转为16进制,使用printf "%xn" tid命令进行调换

[ylp@ylp-web-01 ~]$ printf "%xn" 1406536f1

再使用jstack命令打字与印刷线程货仓音讯,命令格式:jstack pid |grep tid -A 30

[ylp@ylp-web-01 ~]$ jstack 14063 |grep 36f1 -A 30"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007fa35001e800 nid=0x36f1 runnable "GC task thread#1 (ParallelGC)" prio=10 tid=0x00007fa350020800 nid=0x36f2 runnable "GC task thread#2 (ParallelGC)" prio=10 tid=0x00007fa350022800 nid=0x36f3 runnable "GC task thread#3 (ParallelGC)" prio=10 tid=0x00007fa350024000 nid=0x36f4 runnable "GC task thread#4 (ParallelGC)" prio=10 tid=0x00007fa350026000 nid=0x36f5 runnable "GC task thread#5 (ParallelGC)" prio=10 tid=0x00007fa350028000 nid=0x36f6 runnable "GC task thread#6 (ParallelGC)" prio=10 tid=0x00007fa350029800 nid=0x36f7 runnable "GC task thread#7 (ParallelGC)" prio=10 tid=0x00007fa35002b800 nid=0x36f8 runnable "VM Periodic Task Thread" prio=10 tid=0x00007fa3500a8800 nid=0x3700 waiting on condition JNI global references: 392

从出口新闻方可见到,此线程是JVM的gc线程。此时得以基本明确是内部存款和储蓄器不足或内部存款和储蓄器败露导致gc线程持续运转,导致CPU占用过高。所以接下去我们要找的内部存款和储蓄器方面包车型地铁难题

KiB Mem: 2046460 total, 1923864 used, 122596 free, 14388 buffers

题目代码如下:

3.3、代码定位

展开项目工程,找到ActivityUtil类的477行,代码如下:

www.129028.com 1Paste_Image.png

找到相关同事精晓后,这段代码会从数据库中拿走配置,并基于数据库中remain的值进行巡回,在循环中会一贯对HashMap实行put操作。

查询数据库中的配置,开掘remain的多少巨大

www.129028.com 2Paste_Image.png

从那之后,难点一定实现。

at java.lang.Thread.sleep(Native Method)

www.129028.com 3

2.1、定位难题进度

应用top命令查看财富占用情形,开采pid为14063的长河占用了大批量的CPU财富,CPU占用率高达776.1%,内部存款和储蓄器占用率也完毕了29.8%

[ylp@ylp-web-01 ~]$ toptop - 14:51:10 up 233 days, 11:40, 7 users, load average: 6.85, 5.62, 3.97Tasks: 192 total, 2 running, 190 sleeping, 0 stopped, 0 zombie%Cpu: 97.3 us, 0.3 sy, 0.0 ni, 2.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 stKiB Mem : 16268652 total, 5114392 free, 6907028 used, 4247232 buff/cacheKiB Swap: 4063228 total, 3989708 free, 73520 used. 8751512 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14063 ylp 20 0 9260488 4.627g 11976 S 776.1 29.8 117:41.66 java 

指令监察和控制当前系统的GC处境,然后经过jmap dump:format=b,file=

atcom.ebao.ls.pa.service.impl.XinmeiEcifQueryPolicyServiceImpl.queryInfoByEcifid(XinmeiEcifQueryPolicyServiceImpl.java:90)

客服同事反馈平台种类运维缓慢,网页卡顿严重,多次重启系统后难题还是留存,使用top命令查看服务器情状,发现CPU占用率过高。

对此那样的主题素材,查看过jstack日志的读者应当都了解,平时状态下,线上绝大繁多线程都以居于TIMED_WAITING状态,而大家这里出标题标线程所处的情形与其是大同小异的,那就特别轻便混淆大家的判别。消除这些主题素材的思路首要如下:通过grep在jstack日记中寻找全体的处于TIMED_WAITING状态的线程,将其导出到有个别文件中,如a1.log,如下是多少个导出的日记文件示例:"Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007fe690064000 nid=0xd07 waiting on condition [0x0000000000000000]

用ps -mp 27839 -o THREAD,tid| sort -rn查看该进度下线程CPU占用率(恐怕用top -H -p 27839查看)

3.2、剖判客栈

利用jstack命令查看进度的库房情况

[ylp@ylp-web-01 ~]$ jstack 14063 >>jstack.out

把jstack.out文件从服务器获得地面后,用编辑器查找带有项目目录并且线程状态是RUNABLE的连锁音信,从图中可以看出ActivityUtil.java类的447行正在利用HashMap.put()方法

www.129028.com 4Paste_Image.png

内部存款和储蓄器占用不高,可是Full GC次数依旧非常多,此时可能是显得的System.gc()调用导致GC次数过多,那足以因而增加-XX:+DisableExplicitGC来剥夺JVM对显示GC的响应。

at org.springframework.util.LinkedCaseInsensitiveMap.get(LinkedCaseInsensitiveMap.java:117)

2.2、定位难题线程

行使ps -mp pid -o THREAD,tid,time命令查看该进度的线程意况,开掘该进程的多少个线程占用率异常高

[ylp@ylp-web-01 ~]$ ps -mp 14063 -o THREAD,tid,timeUSER %CPU PRI SCNT WCHAN USER SYSTEM TID TIMEylp 361 - - - - - - 02:05:58ylp 0.0 19 - futex_ - - 14063 00:00:00ylp 0.0 19 - poll_s - - 14064 00:00:00ylp 44.5 19 - - - - 14065 00:15:30ylp 44.5 19 - - - - 14066 00:15:30ylp 44.4 19 - - - - 14067 00:15:29ylp 44.5 19 - - - - 14068 00:15:30ylp 44.5 19 - - - - 14069 00:15:30ylp 44.5 19 - - - - 14070 00:15:30ylp 44.5 19 - - - - 14071 00:15:30ylp 44.6 19 - - - - 14072 00:15:32ylp 2.2 19 - futex_ - - 14073 00:00:46ylp 0.0 19 - futex_ - - 14074 00:00:00ylp 0.0 19 - futex_ - - 14075 00:00:00ylp 0.0 19 - futex_ - - 14076 00:00:00ylp 0.7 19 - futex_ - - 14077 00:00:15

从出口消息方可看看,14065~14072里边的线程CPU占用率都极高

at com.aibaobei.chapter2.eg4.SyncTask$$Lambda$1/1791741888.run(Unknown Source)

java.lang.Thread.State: RUNNABLE

透过排查获得这一个线程之后,大家得以三番八遍对其货仓音信进行排查,假诺该线程本人就应有处于等候状态,举例顾客创制的线程池中居于空闲状态的线程,那么这种线程的库房消息中是不会蕴藏顾客自定义的类的。这个都足以解决掉,而剩余的线程基本上就能够分明是大家要找的有毛病的线程。通过其货仓音信,大家就能够得出具体是在哪些岗位的代码导致该线程处于等候处境了。

2.假设出难题的进程pid是一千,用top -H -p 一千翻看该进度下线程CPU占用率,可能用ps -mp 一千 -o THREAD,tid,time | sort -rn查看。

代码中一回拿走了汪洋的对象,导致内部存款和储蓄器溢出,此时得以由此eclipse的mat工具查看内部存款和储蓄器中有哪些对象相当多;

www.129028.com,atcom.ebao.ls.pa.service.impl.XinmeiEcifQueryPolicyServiceImpl.queryBasicPolicyInfo(XinmeiEcifQueryPolicyServiceImpl.java:186)

对于这几种情景,通过翻看CPU和种类内部存款和储蓄器情状是不只怕查看出实际难题的,因为它们相对来讲都是独具一定阻塞性操作,CPU和连串内部存款和储蓄器使用意况都不高,不过效果却异常慢。上边我们就因此查阅系统日志来一步一步甄别上述三种难点。1. Full GC次数过多

at java.util.HashMap.get(HashMap.java:417)

该进度下的次第线程运市价况如下:top - 08:31:16 up 30 min, 0 users, load average: 0.75, 0.59, 0.35

atcom.ebao.ls.pa.service.impl.XinmeiEcifQueryPolicyServiceImpl.completePolicyCoverageInfo(XinmeiEcifQueryPolicyServiceImpl.java:240)

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

如图top命令截图,某系统某服务器出现CPU占用率持续满载状态,pid为27839的java进度负载极高,双核CPU占用率近200%。

at com.aibaobei.chapter2.eg2.UserDemo.main(UserDemo.java:9)

www.129028.com 5

"DestroyJavaVM" #12 prio=5 os_prio=31 tid=0x00007fe690066000 nid=0x2603 waiting on condition [0x0000000000000000]

USER     %CPU PRI SCNT WCHAN  USER SYSTEM   TID

如若由此jstack能够查阅到死锁状态,则足以检查爆发死锁的五个线程的实际阻塞点,进而管理相应的标题。

除此以外还应该有别的的情况,比如在三个ETL项目中,线上系统实行一段时间就能够时有产生"java.lang.OutOfMemoryError: unable to create new native thread"。原因无疑是出于系统成立了多量线程而从不回收爆发的内部存款和储蓄器溢出(具体原因可参照JVM中可转移的最大Thread数量)。这就不是某些线程导致的标题了,只可以用jstack将JVM线程新闻全体导出。通过观察日志开掘该系列中设有多量jsch创造的运作态线程,通过代码发掘项目中采取了jsch提供的sftp上传下载成效,有个别地点并未有调用关闭措施,导致线程未有健康停止。

通过 top命令查看CPU情状,倘使CPU相比较高,则经过top -Hp

可稳定到标题代码为基本系统代码XinmeiEcifQueryPolicyServiceImpl.java:240

假若由此 top 命令见到CPU并不高,并且系统内部存储器占用率也正如低。此时就足以虚拟是不是是由于另外二种情景导致的标题。具体的能够依赖具体情形分析:

3.若是查得耗费时间线程ID为1002,将该线程ID转变为16进制格式:printf "%xn" 1002,得到3ea,用jstack 一千 |grep 3ea -A 30查看java线程栈,寻觅难点代码。

at java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)

在专门的学业中碰着的四个案例:

能够旁观,在经过为9的Java程序中相继线程的CPU占用情状,接下去我们得以经过jstack命令查看线程id为10的线程为啥费用CPU最高。须求小心的是,在jsatck命令显示的结果中,线程id都调换到了十六进制方式。能够用如下命令查看转变结果,也足以找一个没有错总结器实行改动:root@a39de7e7934b:/# printf "%xn" 10

查得耗费时间线程ID为29736,将该线程ID调换为16进制格式:printf "%xn"29736,获得结果7428,用jstack27839|grep 7428 -A 30查看java线程旅馆信息:

at java.lang.Thread.sleep(Thread.java:340)

展现结果首行如下:

拍卖过线上难题的同班好多都会境遇系统溘然运营缓慢,CPU 百分百,以及Full GC次数过多的标题。当然,这么些题指标最终致使的直观现象就是系统运作缓慢,而且有雅量的告警。本文重要针对系统运转缓慢这一标题,提供该难题的排查思路,进而稳固出题指标代码点,进而提供化解该难点的思路。

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

KiB Swap: 1048572 total, 0 used, 1048572 free. 1192352 cached Mem

at java.util.HashMap.getEntry(HashMap.java:465)

at java.lang.Thread.sleep(Thread.java:340)

"SofaBizProcessor-4-thread-28" prio=10 tid=0x00007f6d40067000 nid=0x7428 runnable [0x00007f6cebefb000]

[GC (Allocation Failure) [DefNew: 2795K->0K, 0.0001504 secs][Tenured: 262546K->402K, 0.0012949 secs] 265342K->402K, [Metaspace: 3109K->3109K], 0.0014699 secs] [Times: user=0.00

  1. 用top命令找到CPU占用率高的java进程pid,只怕ps -aux|grep java查看全部java进度的pid。

at com.aibaobei.user.controller.UserController.detail(UserController.java:18)

例行解决思路:

java.lang.Thread.State: TIMED_WAITING

admin 192   19    - -         -      - 29736

java.lang.Thread.State: TIMED_WAITING

此处的VM Thread一行的终极展现nid=0xa,这里nid的意思正是操作系统线程id的意思。而VM Thread指的就是渣滓回收的线程。这里大家多数能够鲜明,当前系统缓慢的源委主借使污源回收过于频仍,导致GC停立刻间较长。大家由此如下命令能够查看GC的景况:root@8d36124607a0:/# jstat -gcutil 9 1000 10

对此死锁,这种意况大致很轻松察觉,因为jstack能够支持大家检查死锁,何况在日记中打字与印刷具体的死锁线程消息。如下是二个产生死锁的一个jstack日志示例:

那边打字与印刷结果评释该线程在jstack中的表现方式为0xa,通过jstack命令我们得以见见如下音信:"main" #1 prio=5 os_prio=0 tid=0x00007f8718009800 nid=0xb runnable [0x00007f871fe41000]

代码中有些地方读取数据量不小,导致系统内部存款和储蓄器耗尽,进而致使Full GC次数过多,系统缓慢;

在前头第一点中,大家讲到,CPU过高或者是系统往往的进行Full GC,导致系统缓慢。而我辈日常也肯能碰着相比较耗费时间的精打细算,导致CPU过高的图景,此时查看格局实际与地点的特别类似。首先大家经过top命令查看当前CPU消耗过高的长河是哪位,从而获得进度id;然后通过top -Hp

at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)

at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)

image.png

本文主要教授了线上恐怕出现的四种导致系统缓慢的场地,详细剖析了每个状态发生时的风貌,已经依照气象大家得以由此什么样措施固定赢得是这种原因变成的系统缓慢。简要的说,大家实行线上日志剖判时,首要能够分成如下步骤:

"VM Periodic Task Thread" os_prio=31 tid=0x00007fe68d114000 nid=0xa803 waiting on condition

TAG标签:
版权声明:本文由www.129028.com-澳门金沙唯一官网www129028com发布于编程新闻,转载请注明出处:对于线上系统突然产生的运行缓慢问题,1000查看