记一次 Apache 的代码导致生产问题
引言
二狗:二胖快醒醒,赶紧看看刚才报警邮件,你上次写的保存用户接口耗时(《二胖的参数校验坎坷之路》)大大上升,赶紧排查下原因。
二胖:好的,马上看,内心戏可十足(心里却在抱怨,大中午的搅我发财美梦,刚刚梦见我买的股票又涨停了就被叫醒了)。牢骚归牢骚,自己的问题还是得看啊,毕竟是自己写的bug
,含着泪也要把它修复掉。二胖对分析这种问题还是得心应手的,毕竟已经是久经职场的老油条了。
测试环境复现问题
二胖首先通过内部的监控工具看了下这段时间的网络是否正常,以及cpu
的使用情况、数据库
的耗时等,这些指标看起来都是正常的,唯一稍微有点区别的是这段时间流量上涨了一些,肯定又是公司花钱搞营销砸广告了。接着二胖又通过cat(大众点评开源监控工具)分析了几个请求,每个阶段的耗时看下来都ok
。卧槽这可咋办列居然难倒二胖了,如果生产环境问题可以在测试环境复现就好了,这样解觉问题就简单多了。生产不是流量上涨了一些吗?那测试环境来压测一把吧,二胖果断的下载了一个jmeter(压测工具)在测试环境进行了一把疯狂的压测,果然出现了和生产一样的问题。能够复现问题就好,这样离解决问题就近了一大步。
arthas定位问题
问题是复现了,接下来就是找出接口比较耗时的地方了。一般我们找接口耗时较长的地方,都是通过记录日志打印每一步的耗时。这是比较常见做法,不过二胖记得上次部门技术大拿“二狗”分享过一个神器arthas可以输出方法路径上的每个节点上耗时。苦于一直没有机会拿它来用于实际操作,今天终于可以拿它来好好练手了。安装什么的就不介绍了,这个官网都写的比较详细,并且文档也是中文的,非常容易上手。下面我们就来使用下arthas
吧。
启动成功的界面
下面我们根据arthas提供的trace
命令来看看接口的耗时都是在哪里。
我们从上面可以看出主要耗时是集中在 org.apache.commons.beanutils.BeanUtils#copyProperties
这个方法上面的,不就一个实体之间的属性赋值转换吗,需要这么耗时这么久吗?不科学啊,apache
提供的方法还能这么low
吗?带着这些问题我们看看其他提供的属性拷贝的工具类效率如何。
使用JMH对常见属性赋值操作性能比较
使用
get
、set
方法复制。cglib
的BeanCopier
。Spring
的BeanUtils
apache
的BeanUtils
MapStruct
下面我们就来对上面这些操作来进行一波性能比较。
编写下面的测试类。
最后的测试结果如下所示:
从上述结论中我们可以发现性能最好的是排名 用
get
、set
方法复制,其次是mapStruct
和cglib的BeanCopier
,再接着是Spring的beanUtils
,最后的是apache的BeanUtils
。如果对上述测试性能感兴趣的话,代码都已上传到
github
上可自行下载运行对比下结果。代码地址关于对
JMH
的使用就不介绍了,感兴趣的可自行谷歌。不过如果要进行性能比较的话,真心推荐使用下,结果可以通过导出json
文件然后生成图表。
为什么apacheBeanUtils性能最差
apacheBeanUtils
和spring
的beanUtils
都是底层都是使用反射来进行赋值的,为什么apacheBeanUtils
的性能要差一大截列。源码之下无秘密,下面我们来看看这个方法的源码。
Apache BeanUtils
打印了大量的日志、以及各种转换、类型的判断等等导致性能变差。
而
spring
的beanUtil
直接使用反射省,干净利索,核心代码见下图。
其实在《阿里巴巴开发手册》(可在公众号【java金融】回复“泰山”获取)里面也有说明属性的
copy
避免使用apcheBeanUtils
如果生产环境已经大量使用
Apache BeanUtils
的话需要替换spring BeanUtils
的话需要注意下他们两个虽然提供的方法都是copyProperties
但是他们的参数是反的,这点需要注意下,不要直接换个引入的包名完事。
总结
实际使用中的话一般是不会使用
get
和set
方法复制,容易漏掉属性并且也是一个体力活。推荐使用mapStruct
,在编译过程中,MapStruct
将生成该接口的实现,并且它还可以实现不同名字的映射,比如可以把name
映射到username
,灵活性比较高。二胖感觉今天收获满满啊,一下学到了
jmeter
、arthas
、JMH
三个软件的使用。
结束
由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。
如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。
感谢您的阅读,十分欢迎并感谢您的关注。
关注【java金融】后台回复「666」 领取一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构简历等等。
版权声明: 本文为 InfoQ 作者【java金融】的原创文章。
原文链接:【http://xie.infoq.cn/article/c3546c86a4f92cd55fa121803】。文章转载请联系作者。
评论