上周三早上连续受到报警信息,提示某某服务器磁盘满了,请开发同学尽快处理!
二话不说先拿出电脑,分析一下服务器的日志,发现有这样的日志记录出现了一千三百多万次
msgWorker - thread-16 - xxxMessageListener ... 具体内容省略 复制代码
由于之前的日志里是不会打印这些消息日志的,所以,我猜测是不是 日志级别设置错了 。而且这个消息打印的类并不在项目源码里,而是依赖的jar包中,问题大概是知道了,应该是日志依赖jar包冲突了。
因为系统是线上运行的,所以知道某个类里采用哪个日志框架和使用何种日志级别都是个问题!不过,还好有阿里的Arthas,让你可以轻松解决这类线上问题。
因为我们的线上机器都是将arthas集成到docker镜像里的,所以只需要启动arthas程序即可。
logger --name xxx.xxx.xxx //类的全限定名 复制代码
可以看到,该类的级别是DEBUG,同时用的是logback日志框架,而我们的应用程序用的log4j,因此可以断定是日志依赖冲突。
sc -d ch.qos.logback.classic.Logger 复制代码
依赖的jar包可能有很多,但是只需要找到项目中那些直接引用的jar包即可,最终定位到两个jar包。
对应的解决方案也很简单,新升级的xxx-clieng包,去除logback-core,logback-classic的依赖;原有messageListener的jar包,增加logback-classic的排除,问题解决,整个问题定位过程不超过30分钟。
作为java研发工程师,经常会遇到线上问题,很多线上问题的难点在于说,程序的运行时状态你不清楚,比如:
等等,这些问题,arthas都可以帮助你一步一步解决线上问题。
主要有两种安装方式
##1.第一种方式 arthas-boot.jar curl -O https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar ## github访问较慢,可以使用国内的gitee curl -O https://arthas.gitee.io/arthas-boot.jar ##2.第二种方式 as.sh curl -L https://alibaba.github.io/arthas/install.sh | sh ## 可以将路径配置到环境变量,运行即可 ./as.sh 复制代码
安装完成后,attach到某个java进程上,可以看到启动后的界面
## 该命令主要是输出系统的实时数据,包括线程,内存等,可以快速了解系统状况 dashboard ## jvm类命令,可以辅助帮助排查jvm相关问题 ## 1. 系统环境变量 sysprop ## 2. jvm环境变量 sysenv ## 3. jvm参数 vmoption 复制代码
2.1 拦截某个方法,获取其入参,出参以及异常信息
## params,returnObj, throwExp分别代表入参,出参和异常信息, n,x 表示拦截次数和参数展示深度 watch 类全名 方法名 "{params, returnObj, throwExp}" -n 10 -x 5 复制代码2.2 你也可以对方法路径进行追踪,使用 trace
命令
trace 类全名 方法名 -n 5 ## or stack 类全名 方法名 -n 5 复制代码
上面两种方法可以解决线上运行逻辑的检查,非常实用!
有时,我们需要知道某个类是由哪个类加载器加载的,或者说有些动态生成的类,我们如何知道其源码内容等,这些跟类加载相关的功能,arthas都有相关的功能支持。
## sc (search class),可以查找该类由哪些类加载,由哪些包加载 sc -d 类全名 ## sm (search method),和上面的命令相似 ## jad java class decompile,java类反编译工具,对于动态代理的类有奇效 jad --source-only 类全名@hashcode ## 你甚至可以动态修改某个类的源码,然后重新加载该个类! jad 反编译,然后修改源码文件 mc 编译java文件,生成.class文件 redefine 重新加载.class文件 复制代码
其实,arthas还有火焰图以及ognl表达式相关的功能,可以让你了解应用程序存在哪些热点方法,以及让你更细致的了解深层的java对象,限于篇幅,有兴趣的大家可以至 Arthas官网 学习。