线上和测试环境会经常遇到的问题:
- 性能问题
- 线程问题(过多线程被阻塞)。
- gc过多
- 不恰当的对象的生成和释放
- 突然大批量的请求。
- 大批量的查询结果
- 外部连接缓慢(或超时)
- 硬盘、内存、网络爆满
- 某个流程耗时长。
- 程序逻辑问题
- 代码和部署不一致。
- 代码本身问题。
出了问题如何排查:
- log日志。
- 完善的监控和报警系统。
- 使用线上排查工具。
线上问题排查工具:
- 原生命令:jps、jstack、jmap、jhat、jstat、hprof
- 可视化监控: JProfiler(收费)、Jconsole,VisualVM(非生产环境免费,Jconsole的升级版)
- 命令行集合工具:useful-scripts (作者推荐Arthas)
- 字节码增强工具:greys-anatomy, btrace,Arthas(由greys-anatomy演进而来)
Arthas的介绍:
Arthas能解决的问题:
- 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
- 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
- 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
- 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
- 是否有一个全局视角来查看系统的运行状况?
- 有什么办法可以监控到JVM的实时运行状态?
Arthas不能解决的问题
- 无法看出内存详细信息,需要配合jmap,mat或者VisualVM来解决。
Arthas的优点:
- 比btrace和命令行工具快捷方便,看到的东西更多。
Arthas的缺点:
- 线上长时间的对attach会影响系统性能(btrace和命令行工具也有这个问题)
Arthas 架构图:
Arthas的功能简介:
- 基础命令
help——查看命令帮助信息
cat——打印文件内容,和linux里的cat命令类似
pwd——返回当前的工作目录,和linux命令类似
cls——清空当前屏幕区域
session——查看当前会话的信息
reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
version——输出当前目标 Java 进程所加载的 Arthas 版本号
history——打印命令历史
quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
shutdown——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
keymap——Arthas快捷键列表及自定义快捷键
- jvm相关
dashboard——当前系统的实时数据面板
thread——查看当前 JVM 的线程堆栈信息
jvm——查看当前 JVM 的信息
sysprop——查看和修改JVM的系统属性
sysenv——查看JVM的环境变量
getstatic——查看类的静态属性
New! ognl——执行ognl表达式
New! mbean——查看 Mbean 的信息
- class/classloader相关
sc——查看JVM已加载的类信息
sm——查看已加载类的方法信息
jad——反编译指定已加载类的源码
mc——内存编绎器,内存编绎.java文件为.class文件
redefine——加载外部的.class文件,redefine到JVM里(禁止在生产环境使用)
dump——dump 已加载类的 byte code 到特定目录(非紧急情况请勿在生产环境使用)
classloader——查看classloader的继承树,urls,类加载信息,使用classloader去getResource
- monitor/watch/trace相关
请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 shutdown 或将增强过的类执行 reset 命令。
monitor——方法执行监控
watch——方法执行数据观测
trace——方法内部调用路径,并输出方法路径上的每个节点上耗时
stack——输出当前方法被调用的调用路径
tt——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测。
Arthas使用注意事项:
- 由于添加了部分逻辑,肯定会有影响,并且替换代码的时候需要到SafePoint的时候才能替换,进行STW,如果替换代码过于频繁,那么会频繁执行STW,这个时候会影响性能。
- trace 在执行的过程中本身是会有一定的性能开销,在统计的报告中并未像 JProfiler 一样预先减去其自身的统计开销。所以这统计出来有些许的不准,渲染路径上调用的类、方法越多,性能偏差越大。但还是能让你看清一些事情的。
- (monitor/watch/trace相关)如果您正在观察/追踪高吞吐量方法,您应该预计突然的CPU涌入。 由于Arthas将要更改方法的字节代码,因此JVM的JIT编译器会在检测到更改后将字节代码从本机代码解除优化到解释模式。 实际开销取决于方法的并发性。 否则开销应该很小。
- Watch、trace、stack、tt等命令都必须加上-n,调用次数限制,否则高频率调用很容易撑爆内存。
- Watch、tt、jad由于都会调用retransformClasses,所以在某个命令执行的时候执行另一个命令所做的修改会丢失。如果开两个窗口,一个窗口执行watch/tt等命令,另一个窗口对这个类执行jad,那么可以观察到watch/tt停止了输出。
Arthas原理:
- sc、sm原理:
sc的信息主要从对应的Class中获取。
- jad原理
jad使用的是cfr提供的jar包来进行反编译。
- watch、trace原理
利用jdk1.6的instrument + ASM。
Arthas涉及到的技术:
- Instrumentation
- ASM。
- Ognl
- VirtualMachine