记一次线上Java程序导致服务器CPU占用率过高的问题排除过程

2023-11-03

原文链接:http://www.jianshu.com/p/3667157d63bb

1、故障现象

客服同事反馈平台系统运行缓慢,网页卡顿严重,多次重启系统后问题依然存在,使用top命令查看服务器情况,发现CPU占用率过高。

2、CPU占用过高问题定位

2.1、定位问题进程

使用top命令查看资源占用情况,发现pid为14063的进程占用了大量的CPU资源,CPU占用率高达776.1%,内存占用率也达到了29.8%

[ylp@ylp-web-01 ~]$ top
top - 14:51:10 up 233 days, 11:40,  7 users,  load average: 6.85, 5.62, 3.97
Tasks: 192 total,   2 running, 190 sleeping,   0 stopped,   0 zombie
%Cpu(s): 97.3 us,  0.3 sy,  0.0 ni,  2.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16268652 total,  5114392 free,  6907028 used,  4247232 buff/cache
KiB 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
2.2、定位问题线程

使用ps -mp pid -o THREAD,tid,time命令查看该进程的线程情况,发现该进程的多个线程占用率很高

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

从输出信息可以看出,14065~14072之间的线程CPU占用率都很高

2.3、查看问题线程堆栈

挑选TID为14065的线程,查看该线程的堆栈情况,先将线程id转为16进制,使用printf "%x\n" tid命令进行转换

[ylp@ylp-web-01 ~]$ printf "%x\n" 14065
36f1

再使用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占用过高。
所以接下来我们要找的内存方面的问题

3、内存问题定位

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区内存占用100%,Old区内存占用99.99%,Full GC的次数高达220次,并且频繁Full GC,Full GC的持续时间也特别长,平均每次Full GC耗时6.8秒(1505.439/220)。根据这些信息,基本可以确定是程序代码上出现了问题,可能存在不合理创建对象的地方

3.2、分析堆栈

使用jstack命令查看进程的堆栈情况

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

把jstack.out文件从服务器拿到本地后,用编辑器查找带有项目目录并且线程状态是RUNABLE的相关信息,从图中可以看出ActivityUtil.java类的447行正在使用HashMap.put()方法


Paste_Image.png
3.3、代码定位

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


Paste_Image.png

找到相关同事了解后,这段代码会从数据库中获取配置,并根据数据库中remain的值进行循环,在循环中会一直对HashMap进行put操作。

查询数据库中的配置,发现remain的数量巨大


Paste_Image.png

至此,问题定位完毕。



参考链接:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

记一次线上Java程序导致服务器CPU占用率过高的问题排除过程 的相关文章

  • 【Three.js】第十八章 Particles 粒子

    介绍 粒子 它们非常受欢迎 可用于实现各种效果 如星星 烟 雨 灰尘 火和许多其他东西 粒子的好处是您可以在屏幕上以合理的帧速率显示数十万个粒子 缺点是每个粒子都由一个始终面向相机的平面 两个三角形 组成 创建粒子就像制作网格一样简单 我们
  • 网络爬虫之记一次js逆向解密经历

    1 引言 数月前写过某网站 请原谅我的掩耳盗铃 的爬虫 这两天需要重新采集一次 用的是scrapy redis框架 本以为二次爬取可以轻松完成的 可没想到爬虫启动没几秒 出现了大堆的重试提示 心里顿时就咯噔一下 悠闲时光估计要结束了 仔细分
  • array_unique 去重---php

    php数组去掉重复值的方法 首先创建一个PHP示例文件 然后定义一个数组 最后通过 array unique arr 方法把数组中的元素进行去重即可 1 使用array unique方法进行去重 对数组元素进行去重 我们一般会使用array
  • git 如何拉取项目

    首先 git init 文件夹 使文件夹变成 git 可以操作的 然后注意 本地存放代码的目录下必须是最干净的 没有被git的记录的或者init后目录中有其他文件和git库里不同的就会报错 最后 使用 git pull 拉取 例如 链接是
  • 二分类变量相关性分析spss_SPSS详细教程:Cox回归中,分类变量的PH假定检验

    英国统计学家D R Cox于1972年提出的比例风险回归模型 Proportional hazard regression model 简称Cox回归模型 有效地解决了对于生存资料进行多因素分析的问题 但是Cox回归模型在应用时 有一个非常
  • 1.4亿在线背后-QQ-IM后台架构的演化与启示

    保存于 http pan baidu com s 1bpDZc7d
  • MySQL异常:TIMESTAMP with implicit DEFAULT value is deprecated

    问题 D software mysql mysql 5 7 17 winx64 mysql 5 7 17 winx64 bin gt mysqld initialize 2017 12 13T07 08 35 613357Z 0 Warni
  • 51单片机:TLC549测量电压,并将测量值显示在数码管上

    51单片机 TLC549测量电压 并将测量值显示在数码管上 要求 在51单片机上利用TLC549这个A D转换器测量电压 并将测量值显示在数码管上 电源范围是0 5V 可以实时测量出电压大小并显示出来 仿真电路图 代码如下 TLC549测量
  • 资源分配与调度

    1 资源管理概述 1 1 资源管理的目的和任务 目的 1 保证资源的高利用率 2 在 合理 时间内使所有顾客有获得所需资源的机会 3 对不可共享的资源实施互斥使用 4 防止由资源分配不当而引起的死锁 对资源的管理应包括以下几个方面 1 资源
  • Boost练习程序(program_options)

    include
  • MFC 单文档调用对话框

    1 插入新的Dialog 如下图 2 修改ID位 IDD XMB 3 在单文件的Menu 中选中需要链接的按键 右键添加处理程序 如下图所示 添加完成后 在项目的xxxview cpp中会生成如下函数 4 对新添加的IDD XMB的Dial
  • VS在编译后.obj文件出现错误 error LNK2019: 无法解析的外部符号 的一种可能

    若有包含其他库 且规模较大 在写自己的代码时尽量避免把代码放在如小写 common 这种常见名字的文件夹内 否则容易出现编译成功 但 obj文件找不到某个函数导致错误LNK2019
  • GBase 8a视频配套联系

    1 以下关于粗粒度智能牵引描述正确的是 A 免维护 自动建立 B 每一列数据都会生成一个粗粒度智能牵引 C 牵引的建立和维护对资源的消耗可以忽略不计 D 记录DC内的最大值 最小值 空值 求和值等 答案ACD 2 GBase 8a集群数据库
  • UART和SPI简介

    UART 即通用异步收发器 是一种通用的串行 异步通信总线 该总线有两种数据线 可以实现数据的发送和接收 在嵌入式系统中常用于主机与辅助设备之间的通信 通信基础 并行和串行 并行通信 串行通信 单工通信 双工通信 半双工 发送和接收不可以同
  • c++观察者模式

    观察者模式 1 观察者模式简介 观察者模式也叫发布 订阅模式 模型 视图模式 源 监听器模式以及从属者模式 观察者模式定义了对象之间的一对多依赖关系 使得每当一个对象状态发生改变时 其相关依赖对象皆得到通知并被自动更新 2 实例讲解 假如张
  • wsl linux 安装

    1 首先确保windwos的操作系统 win 10 我的系统版本Microsoft Windows 版本 10 0 17134 285 2 开启 适用于linux的windows子系统 在 控制面板 程序 程序和功能 中 3 下载linux
  • 刚刚微软的3月安全更新中,这几个安全漏洞值得注意

    近日 安全专家建议IT团队应优先修补两个零日漏洞 一个是微软Outlook的认证机制 另一个是web标记的绕过 这两个漏洞是微软在其3月补丁星期二安全更新中披露的74个安全漏洞的一部分 在一篇博文中 Automox的研究人员建议企业在24小
  • 获取map的长度、map与list的区别

    获取map的长度 map与list的区别 1 首先看一下map和list有何区别 List 是存储单列数据的集合 存储的数据是有序并且是可以重复的 Map 存储双列数据的集合 通过键值对存储数据 存储 的数据是无序的 Key值不能重复 va
  • TCP协议三次握手,四次挥手

    TCP建立连接的过程叫做握手 握手需要在客户端和服务器端之间交换三个TCP报文段 称之为三次握手 TCP断开连接的过程叫做挥手 即在客户端和服务器端之间交换四个TCP报文段 称之为四次挥手 下面是一次完整的TCP连接过程 上图中对于发送SY
  • echart 点击事件

    以柱状图为例 点击单个柱形上 myChart off click 在渲染点击事件之前先清除点击事件 一定要加上否则会重复加载先前的点击事件 myChart on click function params console log 获取点击的

随机推荐