简介
安装
直接能通过java运行arthar-boot.jar包(官方推荐,可能适用于全平台吧)
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
复制
通过as.sh shell脚本运行(个人推荐,因为习惯greys的使用方式了)
1,下载
curl -L https://alibaba.github.io/arthas/install.sh | sh
2,将as.sh拷贝到$PATH
cp as.sh /usr/local/bin
3,测试
as.sh -h
Arthas script version: 3.1.1
[INFO] JAVA_HOME: /usr/local/jdk1.8.0_144
Usage:
/usr/local/bin/as.sh [-h] [--target-ip <value>] [--telnet-port <value>]
[--http-port <value>] [--session-timeout <value>] [--arthas-home <value>]
[--use-version <value>] [--repo-mirror <value>] [--versions] [--use-http]
[--attach-only] [-c <value>] [-f <value>] [-v] [pid]
复制
常用命令行参数解释
-h --help 查看帮助
--target-ip 打开远程连接功能时,指定的ip地址,默认为127.0.0.1。0.0.0.0表示监听当前节点上所有的ip
--telnet-port 打开远程连接功能时,指定监听的端口,默认为3658
--http-port 启用http连接的端口,默认为8563,设置为-1可关闭http连接,非常实用,设置后,可通过一个web界面连接进来执行诊断命令
--session-timeout 设置连续不操作的超时时间,默认是30分钟
--attach-only 只启动服务端,不进行连接
-c,--command 指定执行的诊断命令,多个命令使用;分隔
复制
常见使用案例
直接输入as.sh或java -jar arthas-boot.jar,会先列举出系统中的java进程,可通过序号选择attach到指定的进程:
as.sh
Arthas script version: 3.1.1
[INFO] JAVA_HOME: /usr/local/jdk1.8.0_144
Found existing java process, please choose one and hit RETURN.
* [1]: 26529 com.yunmicloud.GiApplicationLauncher
[2]: 18529 com.yunmicloud.Application
[3]: 1059 com.yunmicloud.ApplicationLauncher
[4]: 8102 com.yunmicloud.LicaiAppLauncher
[5]: 29958 com.yunmicloud.ApplicationLauncher
[6]: 5577 com.qingbee.InsuranceRecordLauncher
[7]: 16333 com.qingbee.InsuranceProductLauncher
[8]: 9965 com.yunmicloud.gw.App
[9]: 20334 com.yunmicloud.LoanLauncher
[10]: 16558 com.yunmicloud.loan.schedule.Application
[11]: 2736 com.yunmicloud.WxAppLauncher
[12]: 5394 com.qingbee.ScheduleLauncher
[13]: 20723 com.yunmicloud.CancelInsureLauncher
[14]: 17528 com.qingbee.OtherLauncher
[15]: 28318 com.yunmicloud.ExternalServiceLauncher
Arthas home: /home/yunmi/.arthas/lib/3.1.1/arthas
Calculating attach execution time...
Attaching to 26529 using version /home/yunmi/.arthas/lib/3.1.1/arthas...
real 0m0.789s
user 0m0.526s
sys 0m0.067s
Attach success.
telnet connecting to arthas server... current timestamp is 1566035524
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version 3.1.1
pid 26529
time 2019-08-17 17:52:04
$
复制
attach到某一个进程以后,通过help查看所有支持的命令,通过help command,查看其它命令的详细用法
$ help
NAME DESCRIPTION
help Display Arthas Help
keymap Display all the available keymap for the specified connection.
sc Search all the classes loaded by JVM
sm Search the method of classes loaded by JVM
classloader Show classloader info
jad Decompile class
getstatic Show the static field of a class
monitor Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
stack Display the stack trace for the specified class and method
thread Display thread info, thread stack
trace Trace the execution time of specified method invocation.
watch Display the input/output parameter, return object, and thrown exception of specified method invocation
tt Time Tunnel
jvm Display the target JVM information
ognl Execute ognl expression.
mc Memory compiler, compiles java files into bytecode and class files in memory.
redefine Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)
dashboard Overview of target jvm's thread, memory, gc, vm, tomcat info.
dump Dump class byte array from JVM
options View and change various Arthas options
cls Clear the screen
reset Reset all the enhanced classes
version Display Arthas version
shutdown Shutdown Arthas server and exit the console
session Display current session information
sysprop Display, and change the system properties.
sysenv Display the system env.
history Display command history
cat Concatenate and print files
pwd Return working directory name
mbean Display the mbean information
$ help thread
USAGE:
thread [-h] [-b] [-i <value>] [-n <value>] [id]
SUMMARY:
Display thread info, thread stack
EXAMPLES:
thread
thread 51
thread -n -1
thread -n 5
thread -b
thread -i 2000
WIKI:
https://alibaba.github.io/arthas/thread
OPTIONS:
-h, --help this help
-b, --include-blocking-thread Find the thread who is holding a lock that blocks the most number of threads.
-i, --sample-interval <value> Specify the sampling interval (in ms) when calculating cpu usage.
-n, --top-n-threads <value> The number of thread(s) to show, ordered by cpu utilization, -1 to show all.
<id> Show thread stack
复制
dashboard命令可以实时查看目标进程的thread, memory, gc, vm信息,支持-i 指定刷新时间,默认5s,-n 指定执行的次数
$ dashboard -i 1000 -n 5
ID NAME GROUP PRIORITY STATE %CPU TIME INTERRUPTED DAEMON
8429 Timer-for-arthas-dashboard-1c12564d- system 10 RUNNABLE 51 0:0 false true
100 dubbo-future-timeout-thread-1 main 5 TIMED_WAITI 15 6:37 false true
52 localQuartzScheduler_Worker-10 main 5 TIMED_WAITI 3 0:16 false false
Memory used total max usage GC
heap 84M 128M 128M 66.02% gc.g1_young_generation.count 250
g1_eden_space 14M 23M -1 60.87% gc.g1_young_generation.time(ms) 2968
g1_survivor_space 4M 4M -1 100.00% gc.g1_old_generation.count 0
g1_old_gen 66M 101M 128M 51.95% gc.g1_old_generation.time(ms) 0
nonheap 96M 98M -1 97.87%
Runtime
os.name Linux
os.version 2.6.32-696.23.1.el6.x86_64
java.version 1.8.0_144
java.home /usr/local/jdk1.8.0_144/jre
systemload.average 0.04
复制
jvm命令,可查看attach到的目标JVM的信息。如虚拟机参数,classpath等。
[arthas@2047]$ jvm
RUNTIME
---------------------------------------------------------------------------------------------------------------------------------------------------
MACHINE-NAME 2047@api112
JVM-START-TIME 2019-09-28 06:08:31
MANAGEMENT-SPEC-VERSION 1.2
SPEC-NAME Java Virtual Machine Specification
SPEC-VENDOR Oracle Corporation
SPEC-VERSION 1.8
VM-NAME Java HotSpot(TM) 64-Bit Server VM
VM-VENDOR Oracle Corporation
VM-VERSION 25.144-b01
INPUT-ARGUMENTS -DtaskName=launcher/otherLauncher
-Xmx512m
-Xms512m
-XX:NewRatio=4
-XX:+UseG1GC
-Xss512k
-Ddubbo.registry.file=other.properties
-Dsun.net.inetaddr.ttl=5
-Djava.awt.headless=true
-Djava.net.preferIPv4Stack=true
-XX:HeapDumpPath=/data/logs/other/heapDump.hprof
-XX:-UseGCOverheadLimit
-XX:+PrintClassHistogram
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:ErrorFile=/data/logs/other/hs_err.log
-Dlog.path=/data/logs/other
...
复制
sc命令,可用于查看指定的类加载情况,使用-E选项支持正则表达式查询,使用-d选项可列出详细的类加载明细,如类加载器,对应的jar包路径等,可方便排查jar包冲突引起的问题。
$ sc -d org.springframework.context.support.ClassPathXmlApplicationContext
class-info org.springframework.context.support.ClassPathXmlApplicationContext
code-source /data/yunmi/schedule_package/schedule_20190824160151/lib/spring-context-4.3.17.RELEASE.jar
name org.springframework.context.support.ClassPathXmlApplicationContext
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name ClassPathXmlApplicationContext
modifier public
annotation
interfaces
super-class +-org.springframework.context.support.AbstractXmlApplicationContext
+-org.springframework.context.support.AbstractRefreshableConfigApplicationContext
+-org.springframework.context.support.AbstractRefreshableApplicationContext
+-org.springframework.context.support.AbstractApplicationContext
+-org.springframework.core.io.DefaultResourceLoader
+-java.lang.Object
class-loader +-sun.misc.Launcher$AppClassLoader@4c873330
+-sun.misc.Launcher$ExtClassLoader@6bc248ed
classLoaderHash 4c873330
Affect(row-cnt:1) cost in 6 ms
复制
sm命令,用于查看加载到JVM中指定类的方法,使用方法为:sm 类名 方法名,如果不写,则列出所有的方法,同样支持-d,-E等参数
$ sm -d java.lang.String toUpperCase
declaring-class java.lang.String
method-name toUpperCase
modifier public
annotation
parameters
return java.lang.String
exceptions
declaring-class java.lang.String
method-name toUpperCase
modifier public
annotation
parameters java.util.Locale
return java.lang.String
exceptions
Affect(row-cnt:2) cost in 7 ms.
复制
jad命令,用于反编译指定的类,或指定类的方法。可在线分析,诊断调用不符合业务逻辑的代码。具体用法为:jad 类名 [方法名] 同样也支持-E选项。
$ jad java.lang.String toUpperCase
ClassLoader:
Location:
public String toUpperCase() {
return this.toUpperCase(Locale.getDefault());
}
public String toUpperCase(Locale locale) {
int n;
int n2;
int n3;
int n4;
block14 : {
int n5;
if (locale == null) {
throw new NullPointerException();
}
n4 = this.value.length;
for (n3 = 0; n3 < n4; n3 += n5) {
n2 = this.value[n3];
if (n2 >= 55296 && n2 <= 56319) {
n2 = this.codePointAt(n3);
n5 = Character.charCount(n2);
} else {
n5 = 1;
}
int n6 = Character.toUpperCaseEx(n2);
if (n6 != -1 && n2 == n6) {
continue;
}
break block14;
}
return this;
}
n2 = 0;
char[] arrc = new char[n4];
System.arraycopy(this.value, 0, arrc, 0, n3);
String string = locale.getLanguage();
boolean bl = string == "tr" || string == "az" || string == "lt";
for (int i = n3; i < n4; i += n) {
int n7 = this.value[i];
if ((char)n7 >= '\ud800' && (char)n7 <= '\udbff') {
n7 = this.codePointAt(i);
n = Character.charCount(n7);
} else {
n = 1;
}
int n8 = bl ? ConditionalSpecialCasing.toUpperCaseEx(this, i, locale) : Character.toUpperCaseEx(n7);
if (n8 == -1 || n8 >= 65536) {
char[] arrc2;
if (n8 == -1) {
arrc2 = bl ? ConditionalSpecialCasing.toUpperCaseCharArray(this, i, locale) : Character.toUpperCaseCharArray(n7);
} else {
if (n == 2) {
n2 += Character.toChars(n8, arrc, i + n2) - n;
continue;
}
arrc2 = Character.toChars(n8);
}
int n9 = arrc2.length;
if (n9 > n) {
char[] arrc3 = new char[arrc.length + n9 - n];
System.arraycopy(arrc, 0, arrc3, 0, i + n2);
arrc = arrc3;
}
for (int j = 0; j < n9; ++j) {
arrc[i + n2 + j] = arrc2[j];
}
n2 += n9 - n;
continue;
}
arrc[i + n2] = (char)n8;
}
return new String(arrc, 0, n4 + n2);
}
Affect(row-cnt:2) cost in 1112 ms.
复制
getstatic命令,用于查看某个类的静态属性,具体用法:getstatic 类名 指定的属性名称,如果为*,则可查看该类所有的静态属性
$ getstatic java.lang.String *
field: serialVersionUID
@Long[-6849794470754667710]
field: serialPersistentFields
@ObjectStreamField[][isEmpty=true;size=0]
field: CASE_INSENSITIVE_ORDER
@CaseInsensitiveComparator[
serialVersionUID=@Long[8575799808933029326],
]
Affect(row-cnt:3) cost in 13 ms.
复制
monitor命令,用于监控指定类,方法的统计结果。包括调用次数,成功次数,失败次数,平均响应时间,失败比率等。可通过-c指定统计周期,默认是60s。
$ monitor com.yunmicloud.licai.spi.MonitorRestServiceSPI check
Press Q or Ctrl+C to abort.
Affect(class-cnt:8 , method-cnt:4) cost in 199 ms.
timestamp class method total success fail avg-rt(ms) fail-rate
-------------------------------------------------------------------------------------------------------------------
2019-09-16 18:09:42 org.apache.dubbo.common.bytecode.proxy3 check 17 17 0 1.40 0.00%
timestamp class method total success fail avg-rt(ms) fail-rate
-------------------------------------------------------------------------------------------------------------------
2019-09-16 18:10:42 org.apache.dubbo.common.bytecode.proxy3 check 15 15 0 0.34 0.00%
复制
stack命令,可实时打印出方法调用的堆栈。具体用法:stack 类名 方法名 [条件] 。如果加入了条件,则打印出满足条件的堆栈信息。
[arthas@14149]$ stack com.yunmicloud.licai.spi.MonitorRestServiceSPI check
Press Q or Ctrl+C to abort.
Affect(class-cnt:8 , method-cnt:4) cost in 258 ms.
ts=2019-09-16 18:15:38;thread_name=http-nio-20891-exec-4;id=3f;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@5fc8abca
@sun.reflect.GeneratedMethodAccessor152.invoke()
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
...
复制
thread命令,用于查看指定线程信息,或按cpu使用率的top n线程信息。具体用法:thread [-b] [-i
] [-n ] [id],-i参数,可指定一个采样的间隔,并输出汇总信息。-n参数,可设定按cpu使用率的top n个线程信息。
[arthas@14149]$ thread -n 5
"cat-netty-tcp-data-sender" Id=21 cpuUsage=58% TIMED_WAITING
at java.lang.Thread.sleep(Native Method)
at com.dianping.cat.message.io.TcpSocketSender.processMessage(TcpSocketSender.java:170)
at com.dianping.cat.message.io.TcpSocketSender.run(TcpSocketSender.java:219)
at java.lang.Thread.run(Thread.java:748)
at com.dianping.cat.util.Threads$RunnableThread.run(Threads.java:300)
...
复制
trace命令,用于跟踪某个指定方法调用栈的执行时间。具体用法:trace 类名 方法名 [条件] 。
[arthas@14149]$ trace com.yunmicloud.licai.spi.MonitorRestServiceSPI check
Press Q or Ctrl+C to abort.
Affect(class-cnt:8 , method-cnt:4) cost in 335 ms.
`---ts=2019-09-17 12:00:15;thread_name=http-nio-20891-exec-5;id=40;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@5fc8abca
`---[0.777878ms] org.apache.dubbo.common.bytecode.proxy3:check()
`---[0.5891ms] java.lang.reflect.InvocationHandler:invoke() #0
复制
watch命令,用于动态监测某个指定类的方法,调用的请求参数值,返回值,异常信息。具体用法:watch 类名 方法名 值(params target, returnObj,throwExp) [条件]
#重要选项解释
-b 调用之前打印观测的值
-f 调用完成之后打印观测的值,不加参数时,默认都是调用完成之后打印
-x 展开对象的层级,默认为1,有时候有对象嵌套时,需要设置对应的层级
-e 调用之后出现异常打印观测的值
-s 调用成功之后打印观测的值
#使用示例:
1)查看某个方法调用结束后的返回值,及参数
[arthas@2047]$ watch com.qingbee.system.service.impl.OtherMonitorRestServiceImpl check '{params,returnObj}'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 83 ms.
ts=2019-10-10 11:49:54; [cost=0.084521ms] result=@ArrayList[
@Object[][isEmpty=true;size=0],
@String[other],
]
ts=2019-10-10 11:50:04; [cost=0.04218ms] result=@ArrayList[
@Object[][isEmpty=true;size=0],
@String[other],
]
2)满足条件后输出
[arthas@2047]$ watch com.qingbee.system.service.impl.OtherMonitorRestServiceImpl check returnObj 'returnObj.equals("other")'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 95 ms.
ts=2019-10-10 11:53:33; [cost=0.140196ms] result=@String[other]
ts=2019-10-10 11:53:34; [cost=0.03513ms] result=@String[other]
复制
tt命令,可以记录指定方法每次调用的参数和返回值,与watch命令互补。可快速分析一个方法的调用参数,返回值,异常信息。
#重要选项解释
-t 记录方法调用的明细(返回值,是否执行成功等信息),然后可通过-l选项查看
-l 查看通过-t参数记录方法调用的明细
-i 显示指定记录的调用详情(会显示返回值)
-x 展开返回值对象的明细(与watch的-x参数一样)
-d/--delete-all 删除指定或全部的记录
-i -p 重新调用指定的record记录一次,注意:ThreadLocal的数据会丢失
#使用示例:
[arthas@2047]$ tt -t -x 2 com.qingbee.system.service.impl.OtherMonitorRestServiceImpl check
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 175 ms.
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
---------------------------------------------------------------------------------------------------------------------------------------------------
1009 2019-10-10 13:38:33 0.100924 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1010 2019-10-10 13:38:34 0.052025 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1011 2019-10-10 13:38:35 0.037695 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1012 2019-10-10 13:38:37 0.072666 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1013 2019-10-10 13:38:37 0.038405 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1014 2019-10-10 13:38:37 0.035231 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
2)查看记录:
[arthas@2047]$ tt -l
INDEX TIMESTAMP COST(ms) IS-RET IS-EXP OBJECT CLASS METHOD
---------------------------------------------------------------------------------------------------------------------------------------------------
1008 2019-10-10 13:38:11 0.217115 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1009 2019-10-10 13:38:33 0.100924 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1010 2019-10-10 13:38:34 0.052025 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1011 2019-10-10 13:38:35 0.037695 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1012 2019-10-10 13:38:37 0.072666 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1013 2019-10-10 13:38:37 0.038405 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1014 2019-10-10 13:38:37 0.035231 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
1015 2019-10-10 13:38:38 0.037593 true false 0x11cd6d1e OtherMonitorRestServiceImpl check
3)查看指定记录的详情:
[arthas@2047]$ tt -i 1008
INDEX 1008
GMT-CREATE 2019-10-10 13:38:11
COST(ms) 0.217115
OBJECT 0x11cd6d1e
CLASS com.qingbee.system.service.impl.OtherMonitorRestServiceImpl
METHOD check
IS-RETURN true
IS-EXCEPTION false
RETURN-OBJ @String[other]
Affect(row-cnt:1) cost in 1 ms.
4)重新执行指定的记录:
[arthas@2047]$ tt -i 1008 -p
RE-INDEX 1008
GMT-REPLAY 2019-10-10 14:11:20
OBJECT 0x11cd6d1e
CLASS com.qingbee.system.service.impl.OtherMonitorRestServiceImpl
METHOD check
IS-RETURN true
IS-EXCEPTION false
COST(ms) 0.282964
RETURN-OBJ @String[other]
Time fragment[1008] successfully replayed 1 times.
复制
在k8s中使用
# 1,将arthas做到基础镜像中,后续可进入容器,直接进行诊断(推荐)
FROM jdk版本
# copy arthas
COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas
#2,直接使用:
kubectl exec -it ${pod} --container ${containerId} -- /bin/bash -c "wget https://alibaba.github.io/arthas/arthas-boot.jar && java -jar arthas-boot.jar"
复制