CRUDBoy成长计划(7)— 记一次CPU 100%案例
注意:
- 本次计划针对有一定工作经验,想要提升技术和工作能力的程序员。
- 关于本计划的详情见:CRUD Boy 成长计划
- 宗旨
首先不做理论知识普及,这样的东西太多了,其次,不做自我感动的事情,看上去学了很久,实际上工作用不到,面试问不到。
最后功利的一点说就是为了提高薪资。为了能够在工作中有更好的表现,将代码写的更好,更易用,更好维护,更优雅。也为了,在下一次面试的时候,能够从一群八股文科举选手中脱颖而出。
归根结底,技术岗位最重要的还是解决问题的能力,而不是背书的能力。
由于每个人的经验都是不可复制的,因此,我们需要互相学习互相探索出一条程序员自我成长的路线。整体方向围绕两个核心 职业素养 和 技术能力开展。既为了现在能够把代码写好,把需求做好,也为了日后能够把牛逼吹好,把薪资谈好。
参考资料
解决CPU100%属于是比较有套路的事情,基本解决思路/方案为:
- top 命令找出有问题 Java 进程及线程 id:
- 开启线程显示模式
- 按 CPU 使用率排序
- 记下 Java 进程 id 及其 CPU 高的线程 id
- 用进程 id 作为参数,jstack 有问题的 Java 进程
- 手动转换线程 id 成十六进制(可以用 printf %x 1234)
- 查找十六进制的线程 id(可以用 grep)
- 查看对应的线程栈
具体内容见参考资料:
- CRUDBoy成长计划(6)— CPU100%优秀笔记汇总 文章内包含详细解决步骤,命令以及案例。
- Arthas 用户文档 Arthas是一个比较好的调试工具,相对于传统方法来说,命令更少,信息更全,功能更强。
除此之外,系统的进行问题排查也需要项目本身构建完整的监控体系。
案例
背景
有一次早上发现测试服务被容器kill了,查看日志发现是每天都会被容器 kill -9两次。
于是通过 Grafana skywalking等工具查询,相关数据如下:
通过以上图示可以得到结论如下:
- Young gc非常多
- 容器内存只有 1.5G
- 通过Jvm启动参数可以看到JVM的内存占用情况 最大堆内存为1G
- 容器内存 = JVM(堆内存+堆外内存) + 容器内其他进程内存
- 被kill的原因是容器内存不足,由于JVM最大堆内存不超过1024,所以可以认为被kill的时候,JVM堆外内存 + 容器内其他进程内存 > 512MB
由于grafana缺少JVM监控,无法判断是堆外内存爆了,还是容器内其他进程的原因。
解决方案:
- 提升容器内存到2G,提升容错,执行后未再出现kill -9问题
- grafana增加JVM监控,分析JVM堆外内存使用情况
扩容之后就剩下另一个问题,服务的young gc次数非常的多,并且通过对服务器信息的查看,发现CPU占用非常高,接近100%。
排查问题过程
由于采用的是 Arthas 且对项目比较熟悉,所以排查过程非常简单。如下。
- 通过dashboard命令用于整体展示进程所有线程、内存、GC等情况
- 进一步查看堆栈情况
堆栈中提到的这个包,我个人比较熟悉,是运维添加的一个插件,之前引起过dubbo序列化失败的问题,所以联系运维先去除了插件。
总结
问题排查实际上是比较综合的一件事情,除了合理的方法以外,还需要经验。但是很多东西都是教程模板式的操作,在没有很多经验的时候掌握一些套路也是非常有帮助的,最起码在遇到问题的时候知道一个大致的方向。
最后的建议:关于任何线上的问题,不要着急下结论,不能经验之谈,也不能太着急锁定问题范围,尽可能看到更多指标才能更好的发现问题。