java获取cpu使用率_再一次生产 CPU 高负载排查实践

前言

前几日早上打开邮箱收到一封监控报警邮件:某某 ip 服务器 CPU 负载较高,请研发尽快排查解决,发送时间正好是凌晨。

其实早在去年我也处理过类似的问题,并记录下来:《一次生产 CPU 100% 排查优化实践》

不过本次问题产生的原因却和上次不太一样,大家可以接着往下看。

问题分析

收到邮件后我马上登陆那台服务器,看了下案发现场还在(负载依然很高)。

于是我便利用这类问题的排查套路定位一遍。


首先利用 top -c 将系统资源使用情况实时显示出来 (-c 参数可以完整显示命令)。

接着输入大写 P 将应用按照 CPU 使用率排序,第一个就是使用率最高的程序。

果不其然就是我们的一个 Java 应用。

这个应用简单来说就是定时跑一些报表使的,每天凌晨会触发任务调度,正常情况下几个小时就会运行完毕。


常规操作第二步自然是得知道这个应用中最耗 CPU 的线程到底再干嘛。

利用 top -Hp pid 然后输入 P 依然可以按照 CPU 使用率将线程排序。

这时我们只需要记住线程的 ID 将其转换为 16 进制存储起来,通过 jstack pid >pid.log 生成日志文件,利用刚才保存的 16 进制进程 ID 去这个线程快照中搜索即可知道消耗 CPU 的线程在干啥了。

如果你嫌麻烦,我也强烈推荐阿里开源的问题定位神器 arthas 来定位问题。

比如上述操作便可精简为一个命令 thread -n 3 即可将最忙碌的三个线程快照打印出来,非常高效。

更多关于 arthas 使用教程请参考官方文档。

由于之前忘记截图了,这里我直接得出结论吧:

最忙绿的线程是一个 GC 线程,也就意味着它在忙着做垃圾回收。

GC 查看

排查到这里,有经验的老司机一定会想到:多半是应用内存使用有问题导致的。

于是我通过 jstat -gcutil pid 200 50 将内存使用、gc 回收状况打印出来(每隔 200ms 打印 50次)。

4e566b78a4ea3371b482b378fab6b9ab.png

从图中可以得到以下几个信息:

  • Eden 区和 old 区都快占满了,可见内存回收是有问题的。
  • fgc 回收频次很高,10s 之内发生了 8 次回收((866493-866485)/ (200 *5))。
  • 持续的时间较长,fgc 已经发生了 8W 多次。

内存分析

既然是初步定位是内存问题,所以还是得拿一份内存快照分析才能最终定位到问题。

通过命令 jmap -dump:live,format=b,file=dump.hprof pid 可以导出一份快照文件。

这时就得借助 MAT 这类的分析工具出马了。

问题定位

79b1aa44189c509b33f4820ea0faab58.png

通过这张图其实很明显可以看出,在内存中存在一个非常大的字符串,而这个字符串正好是被这个定时任务的线程引用着。

b90d8ca43ef45afcde8e3b12c41aecd3.png

大概算了一下这个字符串所占的内存为 258m 左右,就一个字符串来说已经是非常大的对象了。

那这个字符串是咋产生的呢?

其实看上图中的引用关系及字符串的内容不难看出这是一个 insertSQL 语句。

这时不得不赞叹 MAT 这个工具,他还能帮你预测出这个内存快照可能出现问题地方同时给出线程快照。

874f5e0b7b8915fccac79ba866f427c5.png

b880c08bf4cfdd6beb68b15ec7022e75.png

最终通过这个线程快照找到了具体的业务代码:

他调用一个写入数据库的方法,而这个方法会拼接一个 insert 语句,其中的 values 是循环拼接生成,大概如下:

1    <insert id="insert" parameterType="java.util.List">
2        insert into xx (files)
3        values
4        <foreach collection="list" item="item" separator=",">
5            xxx
6        </foreach>
7    </insert>

所以一旦这个 list 非常大时,这个拼接的 SQL 语句也会很长。

424f8ed4c5be90f6a41e4a23ece94bfc.png

通过刚才的内存分析其实可以看出这个 List 也是非常大的,也就导致了最终的这个 insert 语句占用的内存巨大。

优化策略

既然找到问题原因那就好解决了,有两个方向:

  • 控制源头 List 的大小,这个 List 也是从某张表中获取的数据,可以分页获取;这样后续的 insert 语句就会减小。
  • 控制批量写入数据的大小,其实本质还是要把这个拼接的 SQL 长度降下来。
  • 整个的写入效率需要重新评估。

总结

本次问题从分析到解决花的时间并不长,也还比较典型,其中的过程再总结一下:

  • 首先定位消耗 CPU 进程。
  • 再定位消耗 CPU 的具体线程。
  • 内存问题 dump 出快照进行分析。
  • 得出结论,调整代码,测试结果。

最后愿大家都别接到生产告警。

你的点赞与分享是对我最大的支持

2eab6f063baca406524453f19026da3a.png

x

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/575022.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《BI那点儿事》三国数据分析系列——蜀汉五虎上将与魏五子良将武力分析,绝对的经典分析...

《BI那点儿事》三国数据分析系列——蜀汉五虎上将与魏五子良将武力分析&#xff0c;绝对的经典分析 原文:《BI那点儿事》三国数据分析系列——蜀汉五虎上将与魏五子良将武力分析&#xff0c;绝对的经典分析献给广大的三国爱好者们&#xff0c;希望喜欢三国的朋友一起讨论&#…

java map取值_Java Set接口 Map 与枚举

Set接口概述一个不包含重复元素的 collection。更确切地讲&#xff0c;set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2&#xff0c;并且最多包含一个 null 元素特点Set接口是无序的 Set 是继承于Collection的接口。它是一个不允许有重复元素的集合。Set可以存储null值,但是nu…

网路工程师要不要学mysql_网络工程师要学什么_网络工程师需要的技能

如果以后想从事网络工程师这个岗位&#xff0c;同学们知道 网络工程师要学什么 吗&#xff1f;本期乔布 网络工程师需要的技能 。关键词&#xff1a; 网络工程师要学什么 &#xff0c; 网络工程师需要的技能网络基础知识&#xff1a;深度网络基本概念&#xff0c;例如>ISO/O…

python执行效果_使用tqdm显示Python代码执行进度功能

在使用Python执行一些比较耗时的操作时&#xff0c;为了方便观察进度&#xff0c;通常使用进度条的方式来可视化呈现。Python中的tqdm就是用来实现此功能的。先来看看tqdm的进度条效果&#xff1a;tqdm的基本用法tqdm最主要的用法有3种&#xff0c;自动控制、手动控制或者用于脚…

cookiesession

cookie机制采用的是在客户端保持状态的方案&#xff0c;而session机制采用的是在服务器端保持状态的方案。 由于采用服务器端保持状态的方案在客户端也需要保存一个标识&#xff0c;所以session机制可能需要借助于cookie机制来达到保存标识的目的&#xff0c;但实际上它还有其他…

python的应用图标_python实现根据图标提取分类应用程序实例

本文实例讲述了python实现根据图标提取分类应用程序&#xff0c;分享给大家供大家参考。具体方法如下&#xff1a;#!/usr/bin/python# -*- coding: utf-8 -*-import Imageimport win32uiimport win32guidef make_regalur_image(img, size (256, 256)):return img.resize(size)…

linux调用ocx插件_Wordpress file manager插件任意文件上传

白斩鸡卫兵实验室近日&#xff0c;Wordpress 插件file manager被爆出严重0day漏洞&#xff0c;本着技术研究角度&#xff0c;和大家分享、探讨其漏洞原因。该修复程序已在同一天发布&#xff0c;并且WP File Manager插件6.9版通过删除允许未经授权的文件上传访问的端点来解决当…

ActiveRecord教程

(一、ActiveRecord基础) ActiveRecord是Rails提供的一个对象关系映射(ORM)层&#xff0c;从这篇开始&#xff0c;我们来了解Active Record的一些基础内容&#xff0c;连接数据库&#xff0c;映射表&#xff0c;访问数据等。   Active Record使用基本的ORM模式&#xff1a;表映…

树莓派安装mysql5.6_Linux上安装MySQL5.6

OS & MySQL的版本号和配置&#xff1a;MySQL Version: 5.6.19Linux Version: Linux boston.oracle.com 2.6.18-164.el5 #1 SMP Thu Sep 3 02:16:47 EDT 2009 i686 i686 i386 GNU/Linux一。下载MySQL安装软件。请到www.oracle.com去找DATABASE DOWNLOAD。下载MySQL须要注冊一…

java获取cpu使用率_2019年阿里P8架构师的解析:最新Java性能测试、调优策略

一、性能测试Ⅰ.测试方法微基准性能测试可以精准定位到某个模块或者某个方法的性能问题&#xff0c;例如对比一个方法使用同步实现和非同步实现的性能差异宏基准性能测试宏基准性能测试是一个综合测试&#xff0c;需要考虑到测试环境、测试场景和测试目标测试环境&#xff1a;模…

Linux下的实模式和保护模式

实模式&#xff1a;&#xff08;即实地址访问模式&#xff09;它是Intel公司80286及以后的x86(80386,80486和80586等)兼容处理器&#xff08;CPU&#xff09;的一种操作模式。实模式被特殊定义为20位地址内存可访问空间上&#xff0c;这就意味着它的容量是2的20次幂&#xff08…

java在线编辑器_微软开源在线代码编辑器——Monaco Editor

介绍Monaco Editor是为VS Code提供支持的代码编辑器&#xff0c;运行在浏览器环境中。编辑器提供代码提示&#xff0c;智能建议等功能。供开发人员远程更方便的编写代码。移动浏览器或移动Web框架不支持Monaco编辑器。简单的理解就是VSCode中的代码编辑器和Monaco Editor使用的…

java的核心类库_Java核心类库,集合框架

Java集合框架的由来&#xff1a;Java最初版本只为最常用的数据结构提供了很少的一组类&#xff1a;比如Vector、Stack、Hashtable、BitSet、Enumerrationr接品&#xff0c;其中Enumerrationr接口提供了一种用于访问任意容器中各个元素的抽象机制。这是一种很明智的选择&#xf…

关于解决Permission is only granted to system apps

一句话&#xff0c;clean一下这个Project&#xff01;就OK了…… 不要被假象迷惑&#xff01;转载于:https://www.cnblogs.com/wytings/p/4156038.html

js splice方法_我用JS刷LeetCode | Day 8

如有兴趣&#xff0c;微信搜索「九零后重庆崽儿」&#xff0c;我们一起学前端。删除排序数组中的重复项:说明&#xff1a;现阶段的解题暂未考虑复杂度问题首发地址&#xff1a;我用JS刷LeetCode | Day 8​www.brandhuang.comQuestion&#xff1a;Given an array nums and a val…

java 删除目录下所有文件_Java删除文件、目录及目录下所有文件的方法实例

前言本文主要实现的功能是删除某个目录及目录下的所有子目录和文件&#xff0c;涉及到的知识点&#xff1a;File.delete()用于删除“某个文件或者空目录”&#xff01;所以要删除某个目录及其中的所有文件和子目录&#xff0c;要进行递归删除。具体代码示例如下&#xff1a;imp…

js 根据掩码位计算可用ip地址_变长子网掩码:轻松分配IP地址(下)

Hello,World.如约而至土土来更文咯[吐舌]图1首先先揭晓一下上一篇文章的答案那就是192.168.1.0/24与192.168.2.0/24不能ping通192.168.1.0/16与192.168.2.0/16能ping通图2还记得土土的提示吗&#xff1f;网络号相同则能够ping通那么根据/24可以看出这两个IP地址有24个网络号,即…

edittext实现自动查询,刷新listview

mEdittextqueryvalue.addTextChangedListener(new TextWatcher() {Overridepublic void onTextChanged(CharSequence s, int start, int before,int count) {/** 从本地数据库查询 */query s.toString(); //s是edittext编辑的内容isaddfalse;pageindex0;refreshView(type, que…

java rsaprivatekey_用ssh-keygen生成的公钥和私钥如何在java中转为RSAPublicKey和RSAPrivateKey...

公钥和私钥是用"ssh-keygen -t rsa"生成的&#xff0c;我把生成的公钥以字符串的形式传入下面的函数(从网上找的)就会报错。public static PublicKey string2PublicKey(String pubStr) throws Exception{ByteBuffer byteBuffer ByteBuffer.wrap(Base64.getDecoder().…

python字典中的值只能是字符串类型_python字典key不能是可以是啥类型

python中字典的key不能是可变类型。字典可存储任意类型对象&#xff0c;其中值可以取任何数据类型&#xff0c;但键必须是不可变的&#xff0c;如字符串、数字或元组。语法格式&#xff1a;【d {key1 : value1, key2 : value2}】。字典是另一种可变容器模型&#xff0c;且可存…