易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 33|回复: 4
收起左侧

java应用导致cpu占用过高问题分析及解决办法

[复制链接]
发表于 2024-11-28 10:13:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
java应用导致cpu占用过高问题分析及解决办法& `% ^9 n! t' R# K6 D" w$ ~& Q
: p3 M4 j1 v7 B

主要介绍了java应用cpu占用过高问题分析及解决方法,具有一定参考价值,需要的朋友可以参考下。 使用jstack分析java程序cpu占用率过高的问题

1,使用jps查找出java进程的pid,如 55001

* b. N6 n, N2 ?) m

[devops@ops_prod_flink_01 neo4j]$ jps

60226 Jps

55001 CommunityEntryPoint


" T& D, G$ Z; g" B5 R6 p3 Z

[devops@ops_prod_flink_01 ~]$ top -p 55001 -H

2、使用 top -p 55001 -H 观察该进程中所有线程的CPU占用

top - 10:05:07 up 537 days, 16:08,  2 users,  load average: 0.10, 2.92, 9.17

Threads:  67 total,   0 running,  67 sleeping,   0 stopped,   0 zombie

%Cpu(s):  1.2 us,  0.8 sy,  0.0 ni, 98.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

KiB Mem : 24636208 total, 10156628 free,  2782836 used, 11696744 buff/cache

KiB Swap:  2097148 total,  2053116 free,    44032 used. 20841700 avail Mem

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

55033 devops    20   0 6395992 692476  22340 S  1.0  2.8   0:03.13 java                                                                                                         

55034 devops    20   0 6395992 692476  22340 S  0.7  2.8   0:03.90 java                                                                                                         

55035 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:03.36 java                                                                                                         

55036 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:02.46 java                                                                                                         

55098 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:00.58 java                                                                                                         

57048 devops    20   0 6395992 692476  22340 S  0.3  2.8   0:00.14 java                                                                                                         

55001 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55006 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:03.62 java                                                                                                         

55007 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55008 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55009 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.08 java                                                                                                         

55010 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55011 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55012 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.09 java                                                                                                         

55013 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.09 java                                                                                                         

55014 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.07 java                                                                                                         

55015 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.18 java                                                                                                         

55016 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55017 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55018 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55019 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55020 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55021 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java                                                                                                         

55022 devops    20   0 6395992 692476  22340 S  0.0  2.8   0:00.00 java      

. P! h" T0 \4 f' ]0 |! ]  E

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

3,找出CPU消耗较多的线程id,如55033,将55033转换为16进制0xd6f4,注意是小写哦

4,使用jstack 55001|grep -A 10 0xd6f4来查询出具体的线程状态

[devops@ops_prod_flink_01 neo4j]$ jstack 55001 |grep -A 10 0xd6f4

"VM Thread" os_prio=0 tid=0x00007fae7c1fb000 nid=0xd6f4 runnable

"Gang worker#0 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c024800 nid=0xd6df runnable

"Gang worker#1 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c026800 nid=0xd6e0 runnable

"Gang worker#2 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c028000 nid=0xd6e1 runnable

"Gang worker#3 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c02a000 nid=0xd6e2 runnable

' E( }: |- [6 d8 p

"Gang worker#4 (Parallel GC Threads)" os_prio=0 tid=0x00007fae7c02c000 nid=0xd6e3 runnable

通过这些线程状态便可基本定位问题之所在。

方法1

1.jps 获取Java进程的PID。

2.jstack pid >> java.txt 导出CPU占用高进程的线程栈。

3.top -H -p PID 查看对应进程的哪个线程占用CPU过高。

4.echo “obase=16; PID” | bc 将线程的PID转换为16进制,大写转换为小写。

5.在第二步导出的Java.txt中查找转换成为16进制的线程PID。找到对应的线程栈。

6.分析负载高的线程栈都是什么业务操作。优化程序并处理问题。

方法2

1.使用top 定位到占用CPU高的进程PID top 通过ps aux | grep PID命令

2.获取线程信息,并找到占用CPU高的线程 ps -mp pid -o THREAD,tid,time | sort -rn

3.将需要的线程ID转换为16进制格式 printf “%x\n” tid

4.打印线程的堆栈信息 jstack pid |grep tid -A 30


4 k% n' W+ d/ ]/ f8 k  T

" b8 H1 i( C/ F' o* e
 楼主| 发表于 2024-11-28 10:22:29 | 显示全部楼层
1.执行“top”命令:查看所有进程占系统CPU的排序。极大可能排第一个的就是咱们的java进程(COMMAND列)。PID那一列就是进程号。
5 s: O7 m$ d) M1 n
6 i! O3 U$ q2 C2.执行“top -Hp 进程号”命令:查看java进程下的所有线程占CPU的情况。" R, Q7 z# l- K0 d
& @0 E' P0 k5 |
3.执行“printf "%x\n 10"命令 :后续查看线程堆栈信息展示的都是十六进制,为了找到咱们的线程堆栈信息,咱们需要把线程号转成16进制。例如,printf "%x\n 10-》打印:a,那么在jstack中线程号就是0xa.
1 ], P8 C' [* c
! ?- i9 u# I! N. g' O& f6 B4.执行 “jstack 进程号 | grep 线程ID”  查找某进程下-》线程ID(jstack堆栈信息中的nid)=0xa的线程状态。如果“"VM Thread" os_prio=0 tid=0x00007f871806e000 nid=0xa runnable”,第一个双引号圈起来的就是线程名,如果是“VM Thread”这就是虚拟机GC回收线程了2 V* [& x; z. q* @% I" H  M

6 C! ]# a4 E! L5.执行“jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计)”,查看某进程GC持续变化情况,如果发现返回中FGC很大且一直增大-》确认Full GC! 也可以使用“jmap -heap 进程ID”查看一下进程的堆内从是不是要溢出了,特别是老年代内从使用情况一般是达到阈值(具体看垃圾回收器和启动时配置的阈值)就会进程Full GC。
7 \' ~; O6 o6 e: R. S
8 m; {) e+ G0 Y6.执行“jmap -dump:format=b,file=filename 进程ID”,导出某进程下内存heap输出到文件中。可以通过eclipse的mat工具查看内存中有哪些对象比较多,飞机票:Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙;
 楼主| 发表于 2024-11-28 10:23:21 | 显示全部楼层
1. 使用top查看系统的资源占用情况
$ _, p- w, S8 V& P, K, N) y, V$ M$ vtop
/ V: N3 Q, @( b- l) v连到生产服务器,执行top命令,发现双核的CPU几乎全被一个PID为5739的进程给用掉了,99.2%的用户空间(也可以叫用户态)消耗,极有可能是出现了死循环。
/ H7 C" Q$ S4 m3 ~& }Java应用造成us高的主要原因是线程一直处于可运行(Runnable)状态,通常这些线程在执行无阻塞操作、循环、正则或纯粹的计算等任务,另一个可能造成us高的原因是频繁GC。, T! v/ q3 p, c7 \

6 t& X+ @* h% i- T2. 使用ps命令查看进程对应的是哪个程序  P, Z5 W" \' |: k
ps
, Y, r8 ]- g! k8 L9 F$ q可以看出,罪魁祸首是ccbs。这里也可以使用jps命令。% f5 e) `  j, n, H5 _
* v, Y, G" `: }' v  i. _9 X# T* E
3. 使用top -p [PID] -H 观察该进程中所有线程的资源占用
' T. ]2 b  i. ?! i1 H, [执行 top -p 5739 -H# x; j! A( U% j' R( ]
top -p -H
* r! ?5 l. i; k, k" D) p4 U0 u0 z" c) m  l  U: V
参数        说明
1 |/ L6 ~* D0 g2 ?0 i-p        需要监控的进程id
: E. g+ Z  {5 G& V-H        显示每个线程的情况,否则就是进程的总状态' K0 Y9 b' f5 L; J1 D: A
发现若干线程实时CPU占用率(%CPU)较高,并且处理机使用时间(TIME+)非常长,6146线程实际占有处理机852分钟40.44秒,那么如何知道这个线程正在干嘛呢?我猜测Java这么成熟的平台,肯定有可以解决问题的工具,毕竟这样的问题很多人都会遇到。
, V( v  r/ O: \; a1 T& N0 g: @. l% i4 k9 u
4.使用jstack查看线程快照
$ Q# ?. T' W6 g. n+ H8 i通过在搜索引擎中查找,我得知通过jstack可以生成java虚拟机当前时刻的线程快照。
+ Q! D! W9 i8 b6 ]4 |: f. m执行jstack 5739 | grep -A 100 nid=0x1802
& U3 U, V6 m2 p( r/ _" Ijstack8 P+ D/ x* b& J6 [% O# R
jstack后面的参数是PID的值,nid的含义是操作系统映射的线程id,可以通过nid的值过滤上面占用CPU较高的6146线程,线程id需要转成十六进制,并且字母要小写。
# \9 D  ^0 X  ^' F通过观察输出,可以看到线程长期处于可运行状态,直接根据堆栈信息找到对应的代码。
% E8 V* }% P1 }- p, W+ R4 M( k
: w, w$ f& g9 i* g5.解决bug
, `" O/ k4 D6 Qcode
2 m( J2 e( V1 d" ^7 T' m这部分代码并不是我写的,很明显这种写法非常不好,一旦serviceAddressType的值不在那三种范围内,就会产生死循环,我重写了这里的逻辑,问题解决。
/ }' {' M! P/ Q4 u+ _! v* e6 c7 d
总结
' }; m0 V/ [$ _/ Y/ U任何数据都可能出错,程序逻辑应该充分考虑出现问题的可能。
& B0 [9 p' ~8 T) _( l1 X& p我们遇到的问题,很可能别人也遇到过,要擅于使用搜索引擎。
 楼主| 发表于 2024-11-28 10:24:02 | 显示全部楼层
1.内存消耗过大,导致Full GC次数过多, w8 {% @% |7 l% h% P0 @" I2 {
执行步骤1-5:1 A' a+ u1 j, i& }

5 ^! B( T: z% w' ?6 W# g多个线程的CPU都超过了100%,通过jstack命令可以看到这些线程主要是垃圾回收线程-》上一节步骤2
5 T/ j* Z5 P( x! o( ?, h  b通过jstat命令监控GC情况,可以看到Full GC次数非常多,并且次数在不断增加。--》上一节步骤5
) v. d4 P6 S1 \. B! T( _" @! Z+ F$ R! ~确定是Full GC,接下来找到具体原因:
3 v5 @; s; Z6 W3 ^( x1 z8 [* B7 p$ w; O+ Q! B
生成大量的对象,导致内存溢出-》执行步骤6,查看具体内存对象占用情况。
3 g1 ?/ O3 W" y7 v' ?! f% |内存占用不高,但是Full GC次数还是比较多,此时可能是代码中手动调用 System.gc()导致GC次数过多,这可以通过添加 -XX:+DisableExplicitGC来禁用JVM对显示GC的响应。( ~. s" ^. k) d; j, B5 Z
2.代码中有大量消耗CPU的操作,导致CPU过高,系统运行缓慢;, C* N  a, O& i0 ?5 i3 E8 G
执行步骤1-4:在步骤4jstack,可直接定位到代码行。例如某些复杂算法,甚至算法BUG,无限循环递归等等。- Y: d. w0 x6 J1 }7 Y
" ]& i) _6 G) C8 V; E. G
4 v% G2 J% `' Q. h+ |! w
6 B* D7 Z  X# G8 P' @8 Y
3.由于锁使用不当,导致死锁。
1 _/ d+ `8 w; N+ A; [- p1 D' K执行步骤1-4: 如果有死锁,会直接提示。关键字:deadlock.步骤四,会打印出业务死锁的位置。/ v0 u7 X# Z1 n3 _) f% \

2 s+ ?6 D& x$ B; ~2 i5 |造成死锁的原因:最典型的就是2个线程互相等待对方持有的锁。
3 R5 X0 W7 Z+ s+ C; w- N: _: a4 E4 q7 m/ y

( r# u/ }5 h- |6 A% s/ _" Y4 M% C6 z9 Y- w9 K7 T6 r
4.随机出现大量线程访问接口缓慢。
% W+ W4 n( e) G& ~5 P6 U; S- y" X代码某个位置有阻塞性的操作,导致该功能调用整体比较耗时,但出现是比较随机的;平时消耗的CPU不多,而且占用的内存也不高。8 H6 c3 C; ]) T5 E9 t* V/ s4 F

) Y) l- X+ q; k思路:
* w( t/ H. M5 v( V7 H; n6 Y5 {' X% Z
8 g- n! g* s7 R首先找到该接口,通过压测工具不断加大访问力度,大量线程将阻塞于该阻塞点。
- c6 z. E2 D7 V. t% g; n+ J6 f0 h+ T  v! ]: Q+ z# ]- `
执行步骤1-4:  H- G0 o5 U! T7 T3 F9 ]
8 R+ V/ M; \; B9 X  Y
复制代码
: }1 Z9 U8 A, Z  p/ k"http-nio-8080-exec-4" #31 daemon prio=5 os_prio=31 tid=0x00007fd08d0fa000 nid=0x6403 waiting on condition [0x00007000033db000]) N* R1 |, \9 U

5 n. }& g- {6 W+ F1 b   java.lang.Thread.State: TIMED_WAITING (sleeping)-》期限等待/ D  L9 M: M$ a, \+ N: z, m# d
8 Y, \2 H2 ^- i
    at java.lang.Thread.sleep(Native Method)
$ H# y7 k2 l$ |* F0 n5 u. C
9 O, f& C7 `( ~    at java.lang.Thread.sleep(Thread.java:340)
: e% h& j7 W7 y3 l1 b+ F5 B" j5 Y/ h1 ^
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)4 l; G4 T' y* r3 _4 E5 G* _# S/ w) J8 Z
* I8 M2 i- ?, T8 d
    at com.*.user.controller.UserController.detail(UserController.java:18)-》业务代码阻塞点
( W3 n, A4 B- b2 A复制代码
, Z9 l  \6 c. I2 X" P$ Q如上图,找到业务代码阻塞点,这里业务代码使用了TimeUnit.sleep()方法,使线程进入了TIMED_WAITING(期限等待)状态。关于线程状态,不理解的飞机票:Thread类源码剖析
/ J+ {, r7 X2 U
/ N8 U: t% ^4 n) c; E8 l5.某个线程由于某种原因而进入WAITING状态,此时该功能整体不可用,但是无法复现;: d" @7 F0 K+ Y. F2 d
执行步骤1-4:jstack多查询几次,每次间隔30秒,对比一直停留在parking 导致的WAITING状态的线程。例如CountDownLatch倒计时器,使得相关线程等待->AQS(AbstractQueuedSynchronizer AQS框架源码剖析)->LockSupport.park()。; `( L% v/ g9 y0 F5 ?+ V0 B

. ^7 C( I* j5 F9 E, L: |复制代码
  b% [& |; H# X+ R; O2 C"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f9de08c7000 nid=0x5603 waiting on condition [0x0000700001f89000]     K) F; z# A1 t5 x& i, c4 I
java.lang.Thread.State: WAITING (parking) ->无期限等待/ d+ L. ?) j( @$ I  ]4 M
at sun.misc.Unsafe.park(Native Method)   
& Z. ^+ x, X; Q7 _, oat java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)   
: V: [; j( U, rat com.*.SyncTask.lambda$main$0(SyncTask.java:8)-》业务代码阻塞点
6 ^! B9 p. R$ p) U- O5 o' rat com.*.SyncTask$$Lambda$1/1791741888.run(Unknown Source)   
; w" b1 M1 J3 A& l' w. Kat java.lang.Thread.run(Thread.java:748), a3 N7 R9 A+ R
复制代码+ p$ M. k0 w# W3 R
 楼主| 发表于 2024-11-28 10:25:16 | 显示全部楼层
问题
# L4 w+ |. N, D8 }1、无限循环的while会导致CPU使用率飙升吗?/ j0 d0 M% l, o6 {( h
2、经常使用Young GC会导致CPU占用率飙升吗?$ R) F+ T% @, l/ H) W) f- r* T
3、具有大量线程的应用程序的CPU使用率是否较高?5 R6 g4 O; B# k+ o$ [
4、CPU使用率高的应用程序的线程数是多少?4 {1 L& B+ D; W' u6 L
5、处于BLOCKED状态的线程会导致CPU使用率飙升吗?
" q) F# Z# v6 w  L& Y6、分时操作系统中的CPU是消耗 us还是 sy?
. q) q7 ~$ _* x5 H
2 @) @: G3 d5 Y# w思路
% o. Q: b& z* h8 U1.如何计算CPU使用率?
4 M' ?) f1 Z) d+ W: dCPU%= 1 - idleTime / sysTime * 1007 E& x' K4 x' |: `) b

% L0 R, q1 L' C, d8 DidleTime:CPU空闲的时间
4 i# N+ t1 ^; [* J& B, e7 S* ~+ Y9 k/ t- D% _6 Q, _/ @
sysTime:CPU处于用户模式和内核模式的时间总和- i/ N5 P) }: ^+ k" P7 k) G$ R1 j' O
, Z! D2 t" N$ g9 S4 s) }
2.与CPU使用率有关的是什么?
* p" q: W, q/ l  @人们常说,计算密集型程序的CPU密集程度更高。
+ B8 w4 f: w- {1 h& [( P9 ?
1 p" E* @* B2 i( Y8 R那么,JAVA应用程序中的哪些操作更加CPU密集?
- q. ?. u  b3 P+ \! }3 p; z8 o: k; s0 v) J
以下列出了常见的CPU密集型操作:
6 t  G# d1 z6 V5 N* }7 r/ g( ?5 P4 O2 P# j: @* x/ v
1、频繁的GC; 如果访问量很高,可能会导致频繁的GC甚至FGC。当调用量很大时,内存分配将如此之快以至于GC线程将连续执行,这将导致CPU飙升。9 j' A! H2 ]4 S4 j! k0 ^7 G
2、序列化和反序列化。稍后将给出一个示例:当程序执行xml解析时,调用量会增加,从而导致CPU变满。& {; d" h8 j5 u( z
3、序列化和反序列化;
" Z9 j" v- U: n$ x# I4、正则表达式。我遇到了正则表达式使CPU充满的情况; 原因可能是Java正则表达式使用的引擎实现是NFA自动机,它将在字符匹配期间执行回溯。/ K& n8 H# K3 n. B9 t# P
5、线程上下文切换; 有许多已启动的线程,这些线程的状态在Blocked(锁定等待,IO等待等)和Running之间发生变化。当锁争用激烈时,这种情况很容易发生。
( T3 l( |% R9 y6、有些线程正在执行非阻塞操作,例如 while(true)语句。如果在程序中计算需要很长时间,则可以使线程休眠。
$ s8 r$ u. u8 T: P& q; [7 N5 i8 }, j  U- R7 I. s" ~
3、CPU是否与进程和线程相关?: L+ e! Y! E0 H, ~' ?
现在,分时操作系统使用循环方式为进程调度分配时间片。如果进程正在等待或阻塞,那么它将不会使用CPU资源。线程称为轻量级进程,并共享进程资源。因此,线程调度在CPU中也是分时的。但在Java中,我们使用JVM进行线程调度。因此,通常,线程调度有两种模式:时间共享调度和抢占式调度。
, v2 C# b" i, R  \
; v9 j, C  {% M4 X* `9 G# h9 o答案
; Z- b; `( t1 z  ?' u9 I- H1、while的无限循环会导致CPU使用率飙升吗?; o; r& H0 g1 X8 t2 X
是。
  K- s( X, a3 w4 T: M; N+ ^
1 `/ X6 m& o0 ~1 Y2 B) T首先,无限循环将调用CPU寄存器进行计数,此操作将占用CPU资源。那么,如果线程始终处于无限循环状态,CPU是否会切换线程?
) L) j3 y  Z3 R
" W3 |, i$ N3 O; }& i- U, }除非操作系统时间片到期,否则无限循环不会放弃占用的CPU资源,并且无限循环将继续向系统请求时间片,直到系统没有空闲时间来执行任何其他操作。整编:微信公众号,搜云库技术团队,ID:souyunku
+ M- ?4 v0 W" F4 T* I- _
# v' D# `7 ?$ u' D! s# @stackoverflow中也提出了这个问题:为什么无意的无限循环增加了CPU的使用?! J6 }/ ^4 q3 z- T, d6 ?
2 M! Q, z* P) Z1 k9 C7 a
https://stackoverflow.com/questi ... ncrease-the-cpu-use6 U. W" t# v/ {0 J

6 B* G$ I$ U# W. ~2、频繁的Young GC会导致CPU占用率飙升吗?' W; S& e$ S; f3 k1 ^8 h
是。
' e% u' @" R" G" A! G( w: q2 c" }# P# W
Young GC本身就是JVM用于垃圾收集的操作,它需要计算内存和调用寄存器。因此,频繁的Young GC必须占用CPU资源。
9 d1 `" [  a" q9 y# b; H' o2 i0 B, x& q5 z" n
让我们来看一个现实世界的案例。for循环从数据库中查询数据集合,然后再次封装新的数据集合。如果内存不足以存储,JVM将回收不再使用的数据。因此,如果所需的存储空间很大,您可能会收到CPU使用率警报。
9 @. |4 T8 M$ H1 }6 \- \2 _, y0 |
3、具有大量线程的应用程序的CPU使用率是否较高?
$ d4 U* p: Q' \8 C不时。
/ F' X4 Z( D6 d; g( Q/ T  Z  T% n6 d
如果通过jstack检查系统线程状态时线程总数很大,但处于Runnable和Running状态的线程数不多,则CPU使用率不一定很高。4 w- u, O; P! z/ F3 N" S

& e9 k( u( |  m5 R我遇到过这样一种情况:系统线程的数量是1000+,其中超过900个线程处于BLOCKED和WAITING状态。该线程占用很少的CPU。
- W7 R9 c$ O. v' j+ V  J9 m' \
9 }* `  F& O% M1 y* O9 k; W但是大多数情况下,如果线程数很大,那么常见的原因是大量线程处于BLOCKED和WAITING状态。% }2 y" e, K8 \& R0 e: S6 B4 y; H( T

+ s+ [3 N) ~/ q2 p4、对于CPU占用率高的应用程序,线程数是否较大?# h- q& i+ V! I6 l! r5 X3 J
不是。, s- K2 I  V1 r) L( Y

/ a9 B% M$ o. b, s$ }" j7 |/ U高CPU使用率的关键因素是计算密集型操作。如果一个线程中有大量计算,则CPU使用率也可能很高。这也是数据脚本任务需要在大规模集群上运行的原因。
2 H" R, g& Z2 k7 C+ t# o* N9 D
/ A/ t5 q8 K9 }& g5 |5、处于BLOCKED状态的线程是否会导致CPU占用率飙升?5 o$ n6 y/ C- [8 V: @! l
不会。
" g; M& n1 a+ n5 P
, L3 S4 H( A; xCPU使用率的飙升更多是由于上下文切换或过多的可运行状态线程。处于阻塞状态的线程不一定会导致CPU使用率上升。3 y, W/ t! U: Q- z0 \
7 O7 {, x* k- q% k, ]
6、如果分时操作系统中CPU的值 us或 sy值很高,这意味着什么?
" _3 ^/ U) N! W9 w- |1 P您可以使用命令查找CPU的值 us和 sy值 top,如以下示例所示:
1 {2 u' n- O1 w8 @6 U: C& D
7 i3 O1 s+ c! @6 p# l1 ^8 x+ J6 L% r. Z% X( x' s# d
us:用户空间占用CPU的百分比。简单来说,高我们是由程序引起的。通过分析线程堆栈很容易找到有问题的线程。整编:微信公众号,搜云库技术团队,ID:souyunku
% [) w" {9 \- g% F& u; S# o. h6 j+ \3 d% V
sy:内核空间占用CPU的百分比。当sy为高时,如果它是由程序引起的,那么它基本上是由于线程上下文切换。  Y' u2 G/ G9 I3 N$ Q7 S

- X9 R5 C. E" O2 S  t  M经验! n1 y5 }; t& n; I1 \; y
如何找出CPU使用率高的原因?下面简要描述分析过程。" O  P7 |. P8 Y) _. M

% k* c; L0 Q* s如果发现应用程序服务器的CPU使用率很高,请首先检查线程数,JVM,系统负载等参数,然后使用这些参数来证明问题的原因。其次,使用jstack打印堆栈信息并使用工具分析线程使用情况(建议使用fastThread,一个在线线程分析工具)。
0 S' l6 E& r9 t/ r& `4 \3 S* _) c6 T/ B9 v7 @
以下是一个真实案例:
7 \' w% `! `; B- `7 U% ?/ `' _1 b$ O
一天晚上,我突然收到一条消息,说CPU使用率达到了100%。然后我用jstack导出了线程栈信息。! E1 ?# n' O' U2 D2 W( T

4 a9 i5 R7 i: m% [2 b; T3 ~+ [7 I2 X
进一步检查日志:* c! ^# @. A3 M. k/ O
5 a) O( R" x- n( O' W
代码语言:javascript
, O& s% S/ x' `: f1 K* U0 ?# @复制
) m* D) G" x) h$ f4 ]( I# lonsumer_ODC_L_nn_jmq919_1543834242875 - priority:10- threadid:0x00007fbf7011e000- nativeid:0x2f093- state:RUNNABLE
, A2 M4 _5 V# {: e' B6 ?+ TstackTrace:$ |" A* f( I5 ?
java.lang.Thread.State:RUNNABLE1 Q5 z9 S: F$ Q! b! c( F0 V1 P
at java.lang.Object.hashCode(NativeMethod)- w+ r& ?8 K4 }# q4 b/ S( H, i
at java.util.HashMap.hash(HashMap.java:362)
7 v# G5 L+ O) @* p4 d$ [at java.util.HashMap.getEntry(HashMap.java:462)
. ~& m, ~% E3 }2 O+ h  f4 o# rat java.util.HashMap.containsKey(HashMap.java:449)
3 Y8 t9 d! `8 Pat com.project.order.odc.util.XmlSerializableTool.deSerializeXML(XMLSerializableTool.java:100)
/ O, Z; a( _% V% f5 h/ H" \3 y; V" Jat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:55)
7 c+ l- y/ p( l, K. G! j/ \* uat com.project.plugin.service.message.resolver.impl.OrderFinishMessageResolver.parseMessage(OrderFinishMessageResolver.java:21)
" C( Q* v4 N4 P/ \7 h" w( ]' gat com.project.plugin.service.message.resolver.impl.AbstractResolver.resolve(AbstractResolver.java:28); `3 O3 t& r( }6 c$ x3 R  A5 E
at com.project.plugin.service.jmq.AbstractListener.onMessage(AbstractListener.java:44)7 Q! P) E. b& o" d! \
现在通过这个日志找到了问题:用于反序列化MQ消息实体的方法导致CPU使用率飙升
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 点击这里给我发消息

GMT+8, 2026-4-8 15:49 , Processed in 0.050326 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表