本篇内容介绍了“Java用Arthas排查生产环境的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
成都创新互联服务项目包括叙州网站建设、叙州网站制作、叙州网页制作以及叙州网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,叙州网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到叙州省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
前言
Arthas是Alibaba开源的Java诊断工具。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。对分秒必争的线上异常,Arthas可帮助我们快速诊断相关问题。
下载安装
下载Arthas的arthas-boot.jar
wget https://alibaba.github.io/arthas/arthas-boot.jar
下载arthas之后,先来了解帮助信息,可以通过java -jar arthas-boot.jar -h命令查看,这里给出了一些例子和参数说明
[root@izwz94a0v1sz0gk4rezdcbz arthas]# java -jar arthas-boot.jar -h [INFO] arthas-boot version: 3.1.4 Usage: arthas-boot [-h] [--target-ip] [--telnet-port ] [--http-port ] [--session-timeout ] [--arthas-home ] [--use-version ] [--repo-mirror ] [--versions] [--use-http] [--attach-only] [-c ] [-f ] [--height ] [--width ] [-v] [--tunnel-server ] [--agent-id ] [--stat-url ] [pid] Bootstrap Arthas EXAMPLES: java -jar arthas-boot.jar java -jar arthas-boot.jar --target-ip 0.0.0.0 java -jar arthas-boot.jar --telnet-port 9999 --http-port -1 java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws' java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws' --agent-id bvDOe8XbTM2pQWjF4cfw java -jar arthas-boot.jar --stat-url 'http://192.168.10.11:8080/api/stat' java -jar arthas-boot.jar -c 'sysprop; thread' java -jar arthas-boot.jar -f batch.as java -jar arthas-boot.jar --use-version 3.1.4 java -jar arthas-boot.jar --versions java -jar arthas-boot.jar --session-timeout 3600 java -jar arthas-boot.jar --attach-only java -jar arthas-boot.jar --repo-mirror aliyun --use-http WIKI: https://alibaba.github.io/arthas Options and Arguments: -h,--help Print usage --target-ip The target jvm listen ip, default 127.0.0.1 --telnet-port The target jvm listen telnet port, default 3658 --http-port The target jvm listen http port, default 8563 --session-timeout The session timeout seconds, default 1800 (30min) --arthas-home The arthas home --use-version Use special version arthas --repo-mirror Use special maven repository mirror, value is center/aliyun or http repo url. --versions List local and remote arthas versions --use-http Enforce use http to download, default use https --attach-only Attach target process only, do not connect -c,--command Command to execute, multiple commands separated by ; -f,--batch-file The batch file to execute --height arthas-client terminal height --width arthas-client terminal width -v,--verbose Verbose, print debug info. --tunnel-server The tunnel server url --agent-id The agent id register to tunnel server --stat-url The report stat url Target pid
启动
启动arthas之前,先启动一个springboot的应用。该demo在地址https://github.com/yangtao...
java -jar ytao-springboot-demo.jar
启动arthas-boot.jar命令
java -jar arthas-boot.jar
这里注意需要启动demo和arthas使用同一权限用户,否则使用attach机制获取不到进程信息(这里刚使用时没注意,遇到过这个问题)。 例:root用户启动 demo,u1用户启动arthas时,打印信息 Can not find java process. Try to pass 
查看源码,在获取进程之后,添加日志输出。结果为空,返回-1,判断结果小于0时,直接退出。 
启动类Bootstrap#main的代码 
进程工具类ProcessUtils#select的代码 
通过上面也分析到,我们启动arthas之前,必须要先启动我们的目标进程,否则arthas可能无法启动。
使用root用户启动成功界面 
选择java进程,这里我们的ytao-springboot-demo是 1,选择后会有连接信息
[INFO] arthas home: /root/.arthas/lib/3.1.4/arthas [INFO] Try to attach process 22005 [INFO] Attach process 22005 success. [INFO] arthas-client connect 127.0.0.1 3658 ,---. ,------. ,--------.,--. ,--. ,---. ,---. / O \ | .--. ''--. .--'| '--' | / O \ ' .-' | .-. || '--'.' | | | .--. || .-. |`. `-. | | | || |\ \ | | | | | || | | |.-' | `--' `--'`--' '--' `--' `--' `--'`--' `--'`-----' wiki https://alibaba.github.io/arthas tutorials https://alibaba.github.io/arthas/arthas-tutorials version 3.1.4 pid 17339 time 2019-10-17 02:29:06
dashboard 数据面板
使用dashboard命令,可以查看线程,内存,GC,以及Runtime信息 
jad 反编译
有时我们会遇到线上代码运行结果不是我们期望的结果,有种情况就是线上代码不是我们想要的版本,但是要查看的话,需要下载后再进行反编译。 这时arthas的jad可以帮助我们线上进行即时反编译,确认代码是否符合我们的版本。
jad com.ytao.service.UserServiceImpl

watch 函数执行信息
使用watch命令可以查看函数的执行信息。watch的参数列表(来自官网)
| 参数 | 参数说明 |
|---|---|
| class-pattern | 类名表达式匹配 |
| method-pattern | 方法名表达式匹配 |
| express | 观察表达式 |
| condition-express | 条件表达式 |
| [b] | 在方法调用之前观察 |
| [e] | 在方法异常之后观察 |
| [s] | 在方法返回之后观察 |
| [f] | 在方法结束之后(正常返回和异常返回)观察 |
| [E] | 开启正则表达式匹配,默认为通配符匹配 |
| [x:] | 指定输出结果的属性遍历深度,默认为 1 |
当我们遇到线上数据bug时,我们一般处理的手段就是开发环境模拟线上数据,从生产日志中查找线索,再或者远程debug。以上不管哪种排查手段,相对都是比较麻烦。 这时Arthas的watch可以帮助我们查看实时的代码执行情况。使用观察表达式可以查看函数的参数,返回值,异常信息。观察表达式主要由OGNL表达式组成,所以可以编写OGNL表达式来执行。
观察表达式的变量
| 变量 | 变量说明 |
|---|---|
| params | 函数的入参 |
| returnObj | 函数的返回值 |
| throwExp | 异常信息 |
| target | 当前对象 |
查看一个函数的入参和返回值
watch com.ytao.service.UserServiceImpl getUser "{params,returnObj}"
打印信息isEmpty=false;size=1可以看到参数为非空,参数数量为一个。查看具体入参信息
watch com.ytao.service.UserServiceImpl getUser "{params[0],returnObj}"
查看异常信息
watch com.ytao.service.UserServiceImpl getUser "throwExp"
当我们传入一个参数为-1时,打印出我们定义的非法参数异常 
watch除了观察表达式外,还能使用条件表达式,以及观察事件点。 注意使用观察事件点时,有些观察表达式的变量不一定存在,比如使用-b时,返回值和异常信息都为空。 
有时我们排查某个函数,不能马上获取到函数的信息,arthas给提供的后台异步任务可以帮助我们记录日志。使用方式和Linux的类似。
watch com.ytao.service.UserServiceImpl getUser "{params,returnObj}" > /log/w.log &查看异步保存的日志 
tt 定位异常调用
上面所介绍的watch可以排查函数的调用情况,比较适用在已知当次调用可能存在的情况后,查看信息。如果一个函数调用n次后,有几次为执行异常,我们要去找出这些异常的调用,在watch中排查就不怎么方便了。 使用tt命令可以较方便查看异常的调用及信息。对com.ytao.service.UserServiceImpl#getUser的函数查看,-t是每次调用该函数都会记录
tt -t com.ytao.service.UserServiceImpl getUser
记录信息 
查看所有记录
tt -l
查看指定函数记录
tt -s 'method.name=="getUser"'
输出信息说明
| 表格字段 | 字段解释 |
|---|---|
| INDEX | 时间片段记录编号,每一个编号代表着一次调用,后续tt还有很多命令都是基于此编号指定记录操作,非常重要。 |
| TIMESTAMP | 方法执行的本机时间,记录了这个时间片段所发生的本机时间 |
| COST(ms) | 方法执行的耗时 |
| IS-RET | 方法是否以正常返回的形式结束 |
| IS-EXP | 方法是否以抛异常的形式结束 |
| OBJECT | 执行对象的hashCode(),注意,曾经有人误认为是对象在JVM中的内存地址,但很遗憾他不是。但他能帮助你简单的标记当前执行方法的类实体 |
| CLASS | 执行的类名 |
| METHOD | 执行的方法名 |
从上面参数中我们看到1003调用是以抛异常的形式结束,因为tt会记录每次调用的信息,所以我们可以查看1003的详细信息
tt -i 1003

trace 查看调用链路
我们常会遇到调用某个api时rt过长,我们就要找出调用链上的某个或几个函数进行优化,我们通常定位几个可能的锚点,打印各个锚点间的rt。或者从日志中找出日志打印的时间点计算出时间差,不管使用哪种方法都比较繁琐。当使用arthas的trace命令可以轻松的完成我们的需求。 trace参数说明
| 参数 | 参数说明 |
|---|---|
| class-pattern | 类名表达式匹配 |
| method-pattern | 方法名表达式匹配 |
| condition-express | 条件表达式 |
| [E] | 开启正则表达式匹配,默认为通配符匹配 |
| [n:] | 命令执行次数 |
| #cost | 方法执行耗时 |
使用trace输出com.ytao.controller.UserController#getUser的信息
trace com.ytao.service.UserServiceImpl getUser
输出结果 
在实际使用使用排查过程中,为了减少无用信息的输出,我们一般会使用#cost过滤耗时不长和jdk自带的函数,可以忽略的调用,减少信息的输出。例如:过滤掉小于1ms的调用
trace com.ytao.service.UserServiceImpl getUser '#cost > 1'
redefine 实现热部署
当我们查找出bug,想要快速上线拯救苍生的时候,Arthas为我们准备了redefine命令来实现热更新。 尽管现在都在倡导jad/mc/redefine热更一条龙,但是线上代码建议本地编译好后再进行替换,避免手误操作。 首先先在UserServiceImpl中添加一行代码 
获取classLoaderHash,通过sc命令获取类的信息
sc -d *UserServiceImpl

执行redefine修改的类
redefine -c 1d56ce6a /usr/local/jar/UserServiceImpl.class
通过打印的信息验证是否更新UserServiceImpl类 
Arthas的使用,除了上文中所讲解到的,还有一些其他的诊断功能,这只是我个人使用的方法。但是使用该类工具一定要有套组合拳,对排查问题过程中,遇到问题有对应的排查手段,并非盲目排查。
“Java用Arthas排查生产环境的方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!
网站栏目:Java用Arthas排查生产环境的方法
链接地址:http://www.jxjierui.cn/article/jjcpdh.html


咨询
建站咨询
