【开发篇】十、Arthas和BTrace在线定位问题
·
前面排查内存溢出,是通过生成的内存快照,当内存较大时,此方法生成、导出快照慢(主要生成堆内存快照的时候,会耽误服务器去处理用户发来的请求,影响体验),且在本地用MAT分析快照文件时,对本地内存大小也有要求(快照的1.5-2倍)。下面用在线定位的方式。
0、补充
将这个插件放到Jmeter的lib目录下:

将这两个插件放到lib/ext目录下:

打开Jmeter:

以上三个分别为:
- 活跃线程数
- 当前请求的响应时长
- 每分钟执行的事务数
添加一个响应时长的监听器,在不去生成内存快照的时候,响应时间较短:

再向服务器上执行jamp生成快照,期间发现响应时间明显变长(本来20ms的,成了500+ms)

下面不用这种导出快照的方式,用在线定位,这种方式对用户请求的影响较小,但同时无法查看到像快照文件那样详细的内存信息。
1、jmap + Arthas
执行
//你服务运行的进程ID
jmap -histo:live 进程ID > 文件名
将内存中存活对象以直方图的形式保存到文件中,如下图,相比之前导出快照导致用户响应时长变成500ms,这里约140ms

在直方图文件中找到内存占用最多的对象(关注自己写的类),即嫌疑最大的对象。使用arthas的stack命令,追踪对象创建的方法被调用的链路。
stack com.plat.Controller.DemoController queryMethod //方法名 类名
2、BTrace
用于线上运行系统的方法追踪,侵入小,对系统性能影响小。
官方地址:https://github.com/btraceio/btrace/releases/latest
解压后,simple目录下是一些脚本例子,可模仿。下面编写一个BTrace脚本:
@BTrace //声明这是一个BTrace脚本
public class TracingUserEntity {
@OnMethod(
clazz="com.plat.entity.UserEntity", //指定要监控的类
method="/.*/" //正则表达式,两个/表示开始和结束,中间的.*代表监控所有的方法
)
public static void traceExecute(){ //该方法在条件满足的时候就会触发
jstack(); //调用BTrace内置的方法,打印所监控的方法被调用时的栈信息
}
}
将btrace工具上传到服务器并添加至环境变量
vi /etc/profile

将自定义的脚本也上传到系统所在服务器,运行:
btrace 进程ID 脚本文件名

3、总结
内存泄漏和内存溢出:
- 内存泄漏:不再使用一个对象了,但其在GC Root引用链上,不会被回收器回收,白占空间
- 内存溢出:内存的使用量超出了JVM分配的上限,OutOfMemory
内存溢出的产生原因:
- 持续的内存泄漏,导致可用空间越来越少。最后来个请求,彻底压垮
- 并发请求,正常Java服务返回数据后,相关对象在内存中被释放,但当并发请求下,或者一次请求很大的数据量下,处理数据的时间变量,半天没返回,导致大量数据对象在内存中,进而OOM
更多推荐
所有评论(0)