不经意的两行代码把CPU使用率干到了90%+ 没源码怎么排查?

开发 前端
arthas profiler比较适用CPU使用率持续较高的场景。通过对热点火焰图的分析,NoSuchMethodException异常相关代码占用了很多CPU时间。

背景介绍

某同学反映某个应用ECS CPU使用率90%+,希望分析下原因。
该应用使用schedulerx来做定时任务执行,每隔一小时执行一次,每次执行5分钟左右,执行任务期间CPU使用率90%+。

问题现象

图1 ECS监控指标

ECS配置是4c8g,从上图来看系统负载已经非常高了。

分析过程

寻找热点代码

arthas profiler比较适用CPU使用率持续较高的场景。通过对热点火焰图的分析,NoSuchMethodException异常相关代码占用了很多CPU时间。

图2 热点火焰图

上图红框中NoSuchMethodException展开后如下图:

图2 异常火焰图

分析异常

ClassUtils

从上图可以看出org.springframework.util.ClassUtils.getStaticMethod调用了Class.getMethod,Class.getMethod抛出了NoSuchMethodException,代码如下。

图3 ClassUtils.getStaticMethod

为了进一步定位问题,需要知道ClassUtils.getStaticMethod方法的入参:

图4 arthas watch

​从上图看出ClassUtils.getStaticMethod方法入参分别是:**clazz:java.util.Date;_methodName:_valueOf;args[0]:**java.sql.Timestamp。上面图片只是截取了一部分,其中methodName还有of、from。

ObjectToObjectConverter

调用ClassUtils.getStaticMethod的地方是org.springframework.core.convert.support.ObjectToObjectConverter.determineFactoryMethod:​

图5 ObjectToObjectConverter.determineFactoryMethod

调用ObjectToObjectConverter.determineFactoryMethod的地方是ObjectToObjectConverter.getValidateMember:

图6 ObjectToObjectConverter.getValidateMember

虽然java.sql.Timestamp是java.util.Date的子类,但是从上面代码可以看出进行了很多次无效的调用。

定位业务代码

为了更准确的定位相关业务代码,我们需要知道抛出NoSuchMethodException的线程栈,可以使用arthas stack,从线程栈我们可以知道在【哪个类哪个方法哪行】发出的调用。

stack org.springframework.util.ClassUtils getStaticMethod 'returnObj==null'

图7 arthas stack

分析业务代码

在我们没有源代码的情况,我们可以使用arthas jad反编译定位到的类,进而分析业务代码,到这里就可以具体定位到问题了。

图8 业务代码

gmt_created、gmt_modified在实体类中的定义:

图9 业务实体类

异常场景回顾

查询数据库,数据库返回ResultSet对象。

遍历ResultSet,将ResultSet每一行映射到相应的业务实体类实例化业务实体类,根据ResultSet.getMetaData()获取每一列的值并将该值set到实体类对应属性上在将gmt_created、gmt_modified解析为java.sql.Timestamp类实例,接着使用ObjectToObjectConverter将java.sql.Timestamp转换为java.util.Date的时候抛出了NoSuchMethodException。

异常场景复现示例代码:

图10 测试代码

图11 测试代码

解决办法

数据库表中gmt_created、gmt_modified类型与实体类中对应字段类型的定义保持一致,可以解决异常。

延申阅读

通过提高BeanPropertyRowMapper相关逻辑的缓存命中率可以进一步优化性能,如提前将转换逻辑放到GenericConversionService类的converters中:

图12 优化逻辑

另外可以通过自定义RowMapper来提高性能,因为BeanPropertyRowMapper并不是高性能的一种实现:

图13 BeanPropertyRowMapper

责任编辑:武晓燕 来源: 今日头条
相关推荐

2015-11-30 18:15:33

华为

2019-01-15 15:04:54

CPU电脑使用率

2023-03-06 08:41:32

CPU使用率排查

2022-12-09 18:00:46

2011-03-03 18:50:52

用友谢志华U9

2009-11-16 17:03:20

Oracle优化CPU

2024-04-11 13:27:19

Linuxtop命令

2014-06-12 20:00:14

CentOS 6Hadoop

2021-05-31 15:53:57

CPU Top命令

2021-08-10 11:45:57

topCPULinux

2022-07-23 21:31:24

KubernetesLinux开源

2014-12-01 13:44:03

cgroupscpulimitlinux

2021-07-06 09:45:03

鸿蒙HarmonyOS应用

2010-04-27 10:32:54

Oracle优化CPU

2019-09-10 08:13:33

LinuxCPU内存

2021-11-11 16:46:02

CPU使用率 .NET

2020-07-08 07:00:00

LinuxCPU应用程序

2019-09-24 14:52:35

CPU负载Linux
点赞
收藏

51CTO技术栈公众号