引子   

  正值周末,娃儿6:30又如闹铃般准时来叫醒了我们。年前离开美菜,又回到了杭州。原本是想有更多时间陪伴娃儿,然而新的工作节奏与工作地点,让我们每天都是早上见面;这不,为了周末可以多玩一会儿,早早就过来唤醒我们。因为前几天我们就约好了周末一起放风筝。有些事儿,我以为只是随口一说,小孩子确真真的记着。

  吃过早饭,拉着媳妇儿,领着娃,带上风筝就出门了。其实我是忐忑的,因为我也从来没有把风筝放起来过。来到草坪上,娃就拉着风筝如脱缰之马跑了起来。小孩子的幸福就这么简单,无关乎风筝能飞多高。

                        

  迎着暖暖朝阳,吹着徐徐春风,一下子感觉2周加班的疲惫都消散了。然而,一阵儿急促的“钉钉”声打破了难得的宁静:Warning, ***applicaiton, cpu 高于51%,持续2分钟。此服务涉及大部分单车投放操作,目前是新老并用,我们是新服务,tps不高,但业务非常重要。于是拉着还未尽兴的娃儿,回去处理问题了。当然我的内心是紧张而喜悦的,每次的故障就是一次学习的机会。

问题分析  

  既然是cpu告警,首先查看cpu最近的使用情况,一看得到两条信息:1,下图中剪头所指的地方就是促发告警的阀值,2,cpu一直在40-50%上下徘徊 。

我想大家看到这个图也明白了:告警是正常的,目前cpu的情况很容易就会促发告警。反思一分钟:整天埋头支撑业务,连系统的如此重要指标都没有关注到。然后迅速回忆最近上线的功能,想到2月底,上线过电子锁的需求,但是系统已经无法查看2月分的cpu日志,接下来我们需要去找出问题。

排除内存原因

  平时很少有处理生产环境cpu过高问题,真正碰到这样的场景还是蒙圈的。看看网上好些帖子都是说: heap 内存不足,分配内存失败,会导致cpu偏高。首先使用jstat -gcutil 查看内存使用情况,如下图,可见 新生代的区域 survivor0, survivor1,  eden 以及老生代都正常,FGC 也正常。

jstat -gcutil 参数说明如下

  

重新再来

   遇到问题,猜是需要经验的,瞎忙是没用的,既然没经验那就一步一步来验证吧;

1, ps -ef | grep java 找到进程id

  2,  top -H -p 9527 找到占cpu的线程

3,  使用jstack 分别找也上面的线程的具体内容,比如第一个线程 。

a,  转化线程id为16进制   printf '%x\n' ,输出 6d8d, 因为jstack 中线程id 是16进制的。

b,jstack  | grep 6d8d ,找到此线程

c, 再用同样的方法,发现其他几个线程也是 kafka 消费者引起的。

4,知道问题在于消费kafka了,原来上次做电子锁需求时,为了拿到开锁结果,监听了一个kafka topic,这是一个特别核心的topic(后来听其他同事说,这是公司消息量最多的上个topic了),

随手查了下一个小时的数据26亿/h,也就是 70w/s,  如此巨大的tps, 而此服务只有两个结点,cpu维持在50%左右就不奇怪了。

  到这里,我还想再深究下,到底时哪几行代码占了cpu,  那应该如何找到这些代码呢。说来真是特别巧,上周5听了测试同学的性能测试分享,后来还找时间了解了其中的火焰图(flame graph)和arthas , 对就是“火焰图”- 今天的主角儿。关于火焰图有几个基本的知识就可以简单分析了:  

1,y-axis 表示调用父子关系,下面函数是上面的parent;

2 x-axis 表示抽样合并的结果,越宽表示调用频率越高,即执行的时间长;

3 颜色,左右,没有特别的意义。

一开始看到火焰图,也是特别蒙圈的,下面有几个文章特别不错,英文文档读起来不算太复杂,中文的似乎就是翻译英文文档。

英文文档:

 http://www.brendangregg.com/flamegraphs.html , https://queue.acm.org/detail.cfm?id=2927301

中文说明:

http://www.ruanyifeng.com/blog/2017/09/flame-graph.html

火焰图demo:

 https://queue.acm.org/downloads/2016/Gregg7.svg

  

火焰图实践

   1,clone javaFlameGraph,git 地址如下:https://github.com/saquibkhan/javaFlameGraph

有一个地方要特别注意下:javaFlameGraph 核心是调用 FlameGraph中的实现,如图中剪头所指的项目,要确保FlameGraph也下载了。

  

   2,拉出一个节点摘掉流量,上传clone的文件。

   3,到上传文件的所在目录执行  ./flame-gen.sh 27931  ,等待30s, control +c 就开始生成报告了。

  4,报告为当前目录下的  flame.html ,  找开就是生成的火焰图了。如下图。

  

这个图是可交互的,可以点击每个长方形获取更多详情的信息,如图,可看到有很多都是消耗都是 fastjson的 perseobject,因为我们每收到一个消息,会使用fastjson解析,过滤出指定的消息。

 说明下其中几个除kafka相关线程外的线程,参考文章地址:https://blog.csdn.net/clamaa/article/details/70045983

  DestroyJavaVM:

执行main()的线程在main执行完后调用JNI中的 jni_DestroyJavaVM() 方法唤起DestroyJavaVM 线程。JVM在服务器启动之后,就会唤起DestroyJavaVM线程,处于等待状态,等待其它线程(java线程和native线程)退出时通知它卸载JVM。线程退出时,都会判断自己当前是否是整个JVM中最后一个非daemon线程,如果是,则通知DestroyJavaVM 线程卸载JVM。

  Surrogate Locker Thread:

这个线程主要用于配合CMS垃圾回收器使用,它是一个守护线程,其主要负责处理GC过程中,Java层的Reference(指软引用、弱引用等等)与jvm 内部层面的对象状态同步。

结语

  因为工作的原因,很少有机会处理高tps场景下的问题,终于理性的分析了一次生产环境cpu的问题,相信以后的再有这样的情况会从容一些。因为经验不足,文章中也有很多不足的地方,欢迎指出;如果觉得有用,也欢迎点赞鼓励。

   成为一名优秀的程序员!

火焰图--记一次cpu降温过程的更多相关文章

  1. 如何利用火焰图定位 Java 的 CPU 性能问题

     常见 CPU 性能问题 你所负责的服务(下称:服务)是否遇到过以下现象: 休息的时候,手机突然收到大量告警短信,提示服务的 99.9 line 从 20ms 飙升至 10s: 正在敲代码实现业务功能 ...

  2. Linux程序性能分析和火焰图

    Linux程序性能分析和火焰图 Linux程序的性能分析工具数量比较多,涉及到整个操作系统的方方面面,可能是开源的原因吧,相对于Windows来说丰富太多.其中应用分析性能方面Dtrace, Syst ...

  3. 用 CPI 火焰图分析 Linux 性能问题

    https://yq.aliyun.com/articles/465499 用 CPI 火焰图分析 Linux 性能问题   yangoliver 2018-02-11 16:05:53 浏览1076 ...

  4. perf + 火焰图用法 小结

    要对新服务做性能测试,分析代码热点,初识perf,做下总结 perf + 火焰图用法 perf简介 Perf (Performance Event), Linux 系统原生提供的性能分析工具, 会返回 ...

  5. 火焰图&perf命令

    最近恶补后端技术,发现还是很多不懂,一直写业务逻辑容易迷失,也没有成长.自己做系统,也习惯用自己已知的知识来解决,以后应该多点调研,学到更多的东西应用起来. 先学一个新的性能分析命令. NAME pe ...

  6. Linux下用火焰图进行性能分析【转】

    转自:https://blog.csdn.net/gatieme/article/details/78885908 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  7. 火焰图(Flame Graphs)的安装和基本用法

    火焰图(Flame Graphs) 一.概述: 火焰图(flame graph)是性能分析的利器,通过它可以快速定位性能瓶颈点. perf 命令(performance 的缩写)是 Linux 系统原 ...

  8. 记一次获得 3 倍性能的 go 程序优化实践,及 on-cpu / off-cpu 火焰图的使用

    转自:https://mp.weixin.qq.com/s/9IKaXeWTiiQTFlvZzxgsEA 记一次获得 3 倍性能的 go 程序优化实践,及 on-cpu / off-cpu 火焰图的使 ...

  9. CPU火焰图

    y轴:栈深度 x轴:cpu时间 长方形:一个栈(方法) 长度:出现在监视器中的时长(占用cpu的时间) 其他:从左到右的顺序只是按字母排序,无其他意义 火焰图就是看顶层的哪个函数占据的宽度最大.只要有 ...

随机推荐

  1. 7-45 jmu-python-涨工资 (10 分)

    输入一组工资数据,写入列表.对于小于5000的工资,涨1.5倍.并输出涨后的工资数据. 输入格式: 数据之间空格隔开 输出格式: 涨工资后的数据,空格隔开.尾部 不带空格. 输入样例: 3000 40 ...

  2. UBB代码

    UBB代码是HTML(标准通用标记语言下的一个应用)的一个变种,是Ultimate Bulletin Board (国外的一个BBS程序)采用的一种特殊的TAG.您也许已经对它很熟悉了.UBB代码很简 ...

  3. 基础JavaScript练习(三)总结

    任务目的 实践JavaScript数组.字符串相关操作 任务描述 基于任务四进行升级 将新元素输入框从input改为textarea 允许一次批量输入多个内容,格式可以为数字.中文.英文等,可以通过用 ...

  4. SSM动态切换数据源

    有需求就要想办法解决,最近参与的项目其涉及的三个数据表分别在三台不同的服务器上,这就有点突兀了,第一次遇到这种情况,可这难不倒笔者,资料一查,代码一打,回头看看源码,万事大吉 1. 预备知识 这里默认 ...

  5. Python基础-生物信息:找出基因,生物学家使用字母A、C、T和G构成的字符串建模一个基因组。

    生物信息:找出基因,生物学家使用字母A.C.T和G构成的字符串建模一个基因组.一个基因是基因组的子串,它从三元组ATG后开始在三元组TAG.TAA或TGA之前结束.此外,基因字符串的长度是3的倍数,而 ...

  6. python之嵌套 闭包 装饰器 global、nonlocal关键字

    嵌套: 在函数的内部定义函数闭包: 符合开放封闭原则:在不修改源代码与调用方式的情况下为函数添加新功能  # global 将局部变量变成全局变量 num = 100 def fn1(): globa ...

  7. xml模块介绍

      # xml 是一门可拓展的语言 # xml 语法 是用<>包裹的起来的<>就是标签, xml可以由多个<>组成 也可以由单个<>组成, # < ...

  8. Vue2.0 【第一季】第4节 v-text & v-html

    目录 Vue2.0 [第一季]第4节 v-text & v-html 第四节 v-text & v-html Vue2.0 [第一季]第4节 v-text & v-html 第 ...

  9. burpsuit之Spider、Scanner、Intruder模块

    1.spider模块 1.spider模块介绍 被动爬网:(被动爬网获得的链接是手动爬网的时候返回页面的信息中分析发现超链接) 对于爬网的时候遇到HTML表单如何操作: 需要表单身份认证时如何操作(默 ...

  10. .net webapi 接收保存图片到服务器,并居中剪裁压缩图片

    原文链接:https:////www.cnblogs.com/Jackyye/p/12510943.html 每天解决一些c#小问题,在写微信小程序,或者一些手机软件接口,我们经常要用到上传图片到服务 ...