ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

线上CPU飙升排查

2022-07-11 18:02:01  阅读:287  来源: 互联网

标签:used MB 代码 排查 线程 线上 GC CPU


线上CPU飙升排查

目录

准备一份代码

public class Main {

    public static void main(String[] args) {
        int i = 0;
        while (true) {
            i++;
            i--;
        }
    }
}

步骤

top命令找到对应进程

top

image

找到占用最高的线程

方法1

top -Hp 506

image

方法2

ps -mp 506 -o THREAD,tid,time

image

linux下的线程号是10进制,而jdk自带工具中的线程号使用的是16进制,我们需要先把它转换成16进制

将线程号转换成16进制

print "%x\n" 507
# 1fb

使用jdk的工具jstack查看堆栈信息

-A100表示最多显示100行

jstack 506 | grep 1fb -A100

image

我们看到上面直接定位到了,main方法的第7行

如果是那种多线程代码,我们要给线程池中的线程命名,这样便于我们排查到对应代码,这里仅仅作为示范

cpu飙升可能原因

1. 超大对象频繁移动或者创建

超大对象频繁在年轻代中移动,消耗CPU性能

解决思路

  1. 考虑直接将对象放到老年代
  2. 对象能复用则复用,可以使用对象池,避免频繁创建大对象

2 .内存消耗过大,导致Full GC次数过多

我们会在top命令中排查到GC线程的CPU很高,

这样可以使用jstat工具查看GC次数,确认是否为Full GC过多

jstat gcutil 进程id  间隔时间 统计次数

# 样例 jstat -gcutil 506 10 10

image

也可以通过查看老年代的情况判断

jdk 8使用如下命令

jmap -heap 进程id

jdk 9以后使用如下命令

jhsdb jmap --pid 进程id --heap
➜  emmith jhsdb jmap --pid 506 --heap
Attaching to process ID 506, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17.0.3+7-LTS

using thread-local object allocation.
Garbage-First (G1) GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 3309305856 (3156.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 1983905792 (1892.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 22020096 (21.0MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 2097152 (2.0MB)

Heap Usage:
G1 Heap:
   regions  = 1578
   capacity = 3309305856 (3156.0MB)
   used     = 14659584 (13.98046875MB)
   free     = 3294646272 (3142.01953125MB)
   0.4429806321292776% used
G1 Young Generation:
Eden Space:
   regions  = 6
   capacity = 25165824 (24.0MB)
   used     = 12582912 (12.0MB)
   free     = 12582912 (12.0MB)
   50.0% used
Survivor Space:
   regions  = 0
   capacity = 0 (0.0MB)
   used     = 0 (0.0MB)
   free     = 0 (0.0MB)
   0.0% used
G1 Old Generation:
   regions  = 2
   capacity = 186646528 (178.0MB)
   used     = 2076672 (1.98046875MB)
   free     = 184569856 (176.01953125MB)
   1.112622893258427% used

解决思路

  1. 增大堆空间,增大老年代
  2. 将对象放到堆外内存,减少GC
  3. 代码里面可能有System.gc()显示调用,禁用此功能

3. 死循环等CPU密集型代码

代码中可能存在死循环、或者CAS使用不当、或者无线递归

解决思路

  1. 优化代码逻辑,尽量避免无线递归和死循环
  2. 减少CAS次数,或者适当让线程睡眠,如果线程资源竞争特别激烈的情况,将CAS改为使用锁,避免太多的CPU空转

4. 死锁

死锁可以在jstack命令中看到,grep deadlock可以排查是否有死锁

解决思路

如果存在死锁,考虑代码逻辑问题,避免不正确的锁申请顺序

5. 流量激增

集群中别的负载均衡的机器都挂了,请求全部打到某条机器上,导致CPU飙升

解决思路

  1. 限流,熔断降级
  2. 异地多活,保证高可用

参考

https://www.cnblogs.com/dennyzhangdd/p/11585971.html
https://juejin.cn/post/6844904089705250829

标签:used,MB,代码,排查,线程,线上,GC,CPU
来源: https://www.cnblogs.com/emmith/p/16467328.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有