背景
从入职到现在在日常开发中,以及项目上线后遇到挺多问题,例如1、线上出现mq失败率很高的异常 2、bug本地根本无法复现,线上又没有任何异常 3、load 利用率高 4、在压测阶段接口耗时较长 5、遇到发版代码总是不起效果 6、本地启动没有出现包冲突异常,运行的时候出现类冲突异常 等等稀奇古怪,逼到怀疑人生的灵异事件,这个时候想,如果不加日志不改代码不重新发版,又能够做到线上debug的效果,同时能看到数据流转,执行时长等信息,那该是多么爽的一件事,踩了挺多的坑,发现了一个工具arthas,ok,以上问题都能解决。
安装启动
Mac/linux
curl -L http://start.alibaba-inc.com/install.sh | sh
直接shell下面执行./as.sh
,就会进入交互界面
参考链接
举个例子
问题:如果线上load偏高,如果没有arthas,我们查找问题的步骤是什么?
1、top 找到当前最耗cpu资源的进程号
2、ps -mp pid -o THREAD,tid,time 找到这进程下最耗资源的线程id
3、把线程ID,2352 转成十六进制
printf "%x\n" tid
printf "%x\n" 2352
930
4、打印堆栈信息
cd /opt/taobao/java/bin/
./jstack pid |grep tid -A 1000
./jstack 2276 |grep 930 -A 1000
如果线程有问题,相应的定位代码会显示这堆栈中,这里需要4步
5、如果换成arthas来定位问题
thread -n 3
查找最耗资源线程的堆栈
thread tid
这里两步便能定位问题
常用命令
想快速了解系统、应用运行状况
dashboard——当前系统的实时数据面板
thread——查看当前 JVM 的线程堆栈信息
jvm——查看当前 JVM 的信息
类、方法冲突、class文件、classloader继承问题等
sc——查看JVM已加载的类信息
example:sc -df org.apache.commons.lang.StringUtils
项目中使用场景:在docker中查看本地无法发现的包冲突
sm——查看已加载类的方法信息
example: sm org.apache.commons.lang.StringUtils
jad——反编译指定已加载类的源码
项目中使用场景:部署之后,修改的代码没有生效,可以使用这个命令进行查看
example: jad com.funsports.quiz.provider.luckycat.LuckyCatTaskMtopServiceImpl
classloader——查看classloader的继承树,urls,类加载信息
example:classloader -t
查看方法执行参数、异常、返回值、调用路径等
-
请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件;
monitor——方法执行监控
example:monitor -c 5 com.funsports.quiz.provider.luckycat.LuckyCatTaskMtopServiceImpl queryActivityInfo
watch——方法执行数据观测
example:watch com.funsports.quiz.provider.luckycat.LuckyCatTaskMtopServiceImpl queryActivityInfo '{params,returnObj,throwExp}' -n 5 -x 3
项目中应用场景:可以作为线上debug的替代,不用加入日志来观察数据流转
trace——方法内部调用路径,并输出方法路径上的每个节点上耗时
example:trace com.funsports.quiz.provider.luckycat.LuckyCatTaskMtopServiceImpl queryActivityInfo -n 5
应用场景:压测接口,进行预发环境或日常环境监控耗时情况,进行优化调整
stack——输出当前方法被调用的调用路径
example:stack com.funsports.quiz.provider.luckycat.LuckyCatTaskMtopServiceImpl queryActivityInfo -n 5
tt——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
项目中应用场景:和watch的功能差不多,但是它具有穿越时空,时间倒流保留案发现场的能力,复现之前执行过的场景
注意、注意、注意:这个用于查询比较好,如果用户对库有新增,修改操作的容易产生脏数据
ognl
单独使用ognl相关命令访问对象,对应是有状态的才有意义,所以一般是静态属性,静态方法等等,对于ognl使用体验,我觉得项目中针对业务的数据,不建议使用有状态的对象,在高并发下使用不好的话容易出现脏数据,线程私有属性,对象朝生夕死对内存也是友好的,当然静态属性,静态方法也会有的(如果理解不对,请及时交流)
举几个ognl的使用例子:
示例1、简单入参 返回普通对象
ognl -x 3 '@com.funsports.quiz.arthasexample.ognl.OgnlTest@STATIC_STR' -c 221a3fa4
示例2:简单入参 返回对象中包含对象和List
ognl -x 3 '@com.funsports.quiz.arthasexample.ognl.OgnlTest@getPerson("chunfen",18,1)' -c 221a3fa4
示例3: 方法A的返回值当做方法B的入参
ognl -x 2 '#value1=@com.funsports.quiz.arthasexample.ognl.OgnlTest@getPerson("chunfen",18), #value2=@com.funsports.quiz.arthasexample.ognl.OgnlTest@setPerson(#value1) ,{#value1,#value2}' -c 221a3fa4
示例5:方法入参是简单类型列表
ognl -x 3 '@com.funsports.quiz.arthasexample.ognl.OgnlTest@getChilds({"123","456"})' -c 221a3fa4
示例6: 方法入参是一个复杂对象
ognl -x 2 '#obj=new com.funsports.quiz.arthasexample.ognl.Shirc("chunfen",true),@com.funsports.quiz.arthasexample.ognl.OgnlTest@inputObj(#obj)' -c 221a3fa4
放大招,插件
插件下载地址
plugins.jetbrains.com/plugin/1358…
相关学习链接
【Arthas】命令之ognl使用姿势
爱上Java诊断利器Arthas之Arthas idea plugin 的前世今生
apache官方ognl使用语法
arthas官方学习文档
arthas wiki
交流
马老师曾经说过,“未来数据是共同分享的,才能提现它的价值!“,如果有更多项目使用场景,欢迎留言交流
如果您已阅读到此,感谢您对公众号里文章的认可,请动动你可爱的小指头关注微信公众号,每天都有硬核技术文章推送,就算离开也能找到回家的路
二维码如下或者公众号搜索“程序员的十万个为什么”: