如何使用监控诊断工具Arthas(阿尔萨斯)
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率
目录
一、启动安装
二、能使用Arthas(阿尔萨斯做什么
1. 全局查看系统的运行状况
2. 查看指定线程堆栈信息
3. 排查为什么没有执行到修改的代码
4. 方法调用路径,以及性能分析
5. 线上 debug
一、启动安装
##1.下载
wget https://arthas.aliyun.com/arthas-boot.jar;
##2.运行
java -jar arthas-boot.jar;
例如: Windows上使用参考
1.执行java -jar arthas-boot.jar
D:\Soft\arthas-bin>java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.5.4
[INFO] Process 10668 already using port 3658
[INFO] Process 10668 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 10668 org.jboss.Main[2]: 5952[3]: 2240
2.10668为需要监控的进程,是一个启动的Jboss服务,输入10668 前方的序号1回车,开始诊断监控,如下
[INFO] Process 10668 already using port 8563
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 10668 org.jboss.Main[2]: 5952[3]: 2240
1
[INFO] arthas home: D:\Soft\arthas-bin
[INFO] The target process already listen port 3658, skip attach.
[INFO] arthas-client connect 127.0.0.1 3658,---. ,------. ,--------.,--. ,--. ,---. ,---./ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 3.5.4
main_class
pid 10668
time 2022-12-23 16:33:09
二、能使用Arthas(阿尔萨斯)做什么
1. 全局查看系统的运行状况
dashboard 命令,查看当前系统实时数据面板
参数说明
-i : 指刷新的时间间隔
-n: 指刷新次数
例如:
[arthas@10668]$ dashboard
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAE
129 Thread-24 jboss 5 TIMED_WAITING 0.0 0.000 4:23.345 false fal
14 ScannerThread jboss 5 TIMED_WAITING 0.0 0.000 4:22.596 false tru
157 http-0.0.0.0-8091-1 jboss 5 WAITING 0.0 0.000 0:34.304 false tru
-1 C2 CompilerThread0 - -1 - 0.0 0.000 0:27.019 false tru
-1 C2 CompilerThread1 - -1 - 0.0 0.000 0:26.894 false tru
-1 VM Thread - -1 - 0.0 0.000 0:19.734 false tru
-1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:10.420 false tru
-1 GC task thread#4 (ParallelGC) - -1 - 0.0 0.000 0:10.405 false tru
-1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:10.233 false tru
-1 GC task thread#3 (ParallelGC) - -1 - 0.0 0.000 0:10.186 false tru
-1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:9.968 false tru
-1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:9.906 false tru
-1 GC task thread#5 (ParallelGC) - -1 - 0.0 0.000 0:9.765 false tru
-1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:9.672 false tru
52 JCA PoolFiller jboss 5 WAITING 0.0 0.000 0:7.113 false fal
154 arthas-command-execute system 5 RUNNABLE 0.0 0.000 0:5.210 false tru
25 Thread-5 jboss 5 TIMED_WAITING 0.0 0.000 0:4.882 false fal
153 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:1.762 false tru
88 IdleRemover jboss 5 TIMED_WAITING 0.0 0.000 0:0.374 false tru
-1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.296 false tru
49 DefaultQuartzScheduler_QuartzSchedulerThread QuartzScheduler:DefaultQuart 5 TIMED_WAITING 0.0 0.000 0:0.280 false fal
24 Thread-4 jboss 5 TIMED_WAITING 0.0 0.000 0:0.234 false tru
133 AWT-Windows system 6 RUNNABLE 0.0 0.000 0:0.093 false tru
3 Finalizer system 8 WAITING 0.0 0.000 0:0.062 false tru
10 DestroyJavaVM main 5 RUNNABLE 0.0 0.000 0:0.062 false fal
2 Reference Handler system 10 WAITING 0.0 0.000 0:0.046 false tru
145 logback-1 system 5 WAITING 0.0 0.000 0:0.046 false tru
35 ContainerBackgroundProcessor[StandardEngine[jboss.web]] jboss 5 TIMED_WAITING 0.0 0.000 0:0.046 false tru
39 DefaultQuartzScheduler_Worker-0 jboss 5 TIMED_WAITING 0.0 0.000 0:0.046 false fal
40 DefaultQuartzScheduler_Worker-1 jboss 5 TIMED_WAITING 0.0 0.000 0:0.046 false fal
70 Framework Active Thread jboss 5 TIMED_WAITING 0.0 0.000 0:0.031 false fal
138 http-0.0.0.0-8091-Acceptor-0 jboss 5 RUNNABLE 0.0 0.000 0:0.031 false tru
160 stariboss-payment.data jboss 5 TIMED_WAITING 0.0 0.000 0:0.031 false fal
5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.015 false tru
19 GC Daemon system 2 TIMED_WAITING 0.0 0.000 0:0.015 false tru
146 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.015 false tru
Memory used total max usage GC
heap 201M 346M 455M 44.31% gc.ps_scavenge.count 660
ps_eden_space 31M 83M 169M 18.46% gc.ps_scavenge.time(ms) 10991
ps_survivor_space 448K 1024K 1024K 43.75% gc.ps_marksweep.count 69
ps_old_gen 169M 262M 341M 49.85% gc.ps_marksweep.time(ms) 18641
nonheap 175M 178M 304M 57.80%
code_cache 7M 10M 48M 16.48%
ps_perm_gen 167M 168M 256M 65.55%
direct 0K 0K - 0.00%
mapped 1M 1M - 100.00%
Runtime
os.name Windows 7
os.version 6.1
java.version 1.7.0_80
java.home C:\Java\jdk1.7.0_80\jre
systemload.average -1.00
processors 8
timestamp/uptime Mon Dec 26 10:56:25 CST 2022/239168s
[arthas@10668]$
说明
ID:Java级别的线程ID,注意这个ID不能跟jstack中的nativeID一一对应
NAME:线程名
GROUP:线程组名
PRIORITY:线程优先级, 1~10之间的数字,越大表示优先级越高
STATE:线程的状态
CPU%:线程消耗的cpu占比,采样100ms,将所有线程在这100ms内的cpu使用量求和,再算出每个线程的cpu使用占比。
TIME:线程运行总时间,数据格式为
- 分:秒
INTERRUPTED:线程当前的中断位状态
DAEMON:是否是daemon线程
2. 查看指定线程信息
Thread命令
参数说明
n:指定最忙的钱N个线程
b:找出当前是阻塞其他线程的线程
i :指定CPU占比统计的采样时间,单位毫秒
例如 :
thread 显示所有线程信息
thread 1 显示1号线程的运行堆栈
thread -b 查看阻塞的线程信息
thread -n 3 查看CPU使用率最高的3个线程
thread -i 1000 -n 3 ,每过1000秒采用,显示CPU使用最高的线程
#查看最耗CPU的两个线程
[arthas@10668]$ thread -n
"Reference Handler" Id=2 cpuUsage=0.0% deltaTime=0ms time=46ms WAITING on java.lang.ref.Reference$Lock@2ff15375
at java.lang.Object.wait(Native Method)
- waiting on java.lang.ref.Reference$Lock@2ff15375
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)"http-0.0.0.0-8091-1" Id=157 cpuUsage=0.0% deltaTime=0ms time=9812ms RUNNABLE (in native)
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at oracle.net.ns.Packet.receive(Unknown Source)
at oracle.net.ns.DataPacket.receive(Unknown Source)
at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1104)
at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1075)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:480)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3454)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:365)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:824)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:874)
at com.star.sms.dao.utils.SmsJdbcTemplate.update(SmsJdbcTemplate.java:119)
at com.star.sms.dao.utils.SmsJdbcTemplate.modify(SmsJdbcTemplate.java:227)
at com.star.sms.dao.customer.jdbc.CustomerInfoDaoJdbcImpl.modifyCustomer(CustomerInfoDaoJdbcImpl.java:216)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at com.star.common.interceptor.ThreadCacheInterceptor.invoke(ThreadCacheInterceptor.java:66)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
#查看157号线程信息
[arthas@10668]$ thread 157
"http-0.0.0.0-8091-1" Id=157 RUNNABLE (in native)
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at oracle.net.ns.Packet.receive(Unknown Source)
at oracle.net.ns.DataPacket.receive(Unknown Source)
at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.net.ns.NetInputStream.read(Unknown Source)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1104)
at oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1075)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:480)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1190)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3370)
at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3454)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:365)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:824)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:874)
at com.star.sms.dao.utils.SmsJdbcTemplate.update(SmsJdbcTemplate.java:119)
at com.star.sms.dao.utils.SmsJdbcTemplate.modify(SmsJdbcTemplate.java:227)
at com.star.sms.dao.customer.jdbc.CustomerInfoDaoJdbcImpl.modifyCustomer(CustomerInfoDaoJdbcImpl.java:216)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at com.star.common.interceptor.ThreadCacheInterceptor.invoke(ThreadCacheInterceptor.java:66)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy1908.modifyCustomer(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
如果堆栈信息过大, 可以输出日志到文件
默认情况下arthas执行结果是不保存日志的,当然我们通过arthas提供的命令行options进行开启:
关闭日志打印
[arthas@10668]$ options save-result false NAME BEFORE-VALUE AFTER-VALUEsave-result true false
开启日志打印 [arthas@10668]$ options save-result true NAME BEFORE-VALUE AFTER-VALUE
save-result false true[arthas@10668]$
日志会异步保存在 {user.home}/logs/arthas-cache/result.log;
3.排查为什么没有执行到修改的代码
jad 命令
参数说明
- jad 包名.类名 反编译类
- jad包名.类名 方法名 只反编译某个方法
例如:
反编译com.star.sms.service.accept2.dto.NewInstallAcceptDTO如下。jad命令不仅可以查看到ClassLoader还能看到运行的Location信息。 这样可以很清楚了解到运行的是那个包下的类。类覆盖问题就变的很容易发现。
[arthas@10668]$
[arthas@10668]$ jad com.star.sms.service.accept2.dto.NewInstallAcceptDTOClassLoader:
+-com.star.osgi.patch.classloader.BundlePatchURLClassLoader[stariboss-accept_interface]+-org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@4911704b[stariboss-accept_interface:1.0.0(id=99)]+-org.eclipse.osgi.baseadaptor.BaseAdaptor$1@3983efa2Location:
/E:/Jboss/jboss-4.2.3-8.2.1R1-8091-liaoning_821-5g/server/default/./deploy/stariboss.war/tmp/.patchtmp/1671784240888/a_780103_server_22112711_DB-9452.stariboss-accept_interface.jar/** Decompiled with CFR.** Could not load the following classes:* com.star.common.lang.Money* com.star.sms.model.customer.Customer* com.star.sms.service.accept2.dto.AcceptSheetDTO* com.star.sms.service.accept2.dto.BatchNoteInfoDTO*/package com.star.sms.service.accept2.dto;import com.star.common.lang.Money;import com.star.sms.model.customer.Customer;import com.star.sms.service.accept2.dto.AcceptSheetDTO;import com.star.sms.service.accept2.dto.BatchNoteInfoDTO;import java.io.Serializable;import java.util.Map;/** This class specifies class file version 49.0 but uses Java 6 signatures. Assumed Java 6.*/public class NewInstallAcceptDTOimplements Serializable {private static final long serialVersionUID = 5229054864090922612L;private int rowNum;private AcceptSheetDTO acceptSheetDTO;private Customer customer;private Money businessFee;private Money preSavingFee;private Money transferFee;private Map<String, BatchNoteInfoDTO> notedtos;private boolean contactTelRepeatAble = false;public boolean getContactTelRepeatAble() {
/*86*/ return this.contactTelRepeatAble;}public void setContactTelRepeatAble(boolean contactTelRepeatAble) {
/*90*/ this.contactTelRepeatAble = contactTelRepeatAble;}public Customer getCustomer() {
/*38*/ return this.customer;}public void setCustomer(Customer customer) {
/*42*/ this.customer = customer;}public AcceptSheetDTO getAcceptSheetDTO() {
/*30*/ return this.acceptSheetDTO;}public void setAcceptSheetDTO(AcceptSheetDTO acceptSheetDTO) {
/*34*/ this.acceptSheetDTO = acceptSheetDTO;}public Money getBusinessFee() {
/*46*/ return this.businessFee;}public void setBusinessFee(Money businessFee) {
/*50*/ this.businessFee = businessFee;}public Money getPreSavingFee() {
/*54*/ return this.preSavingFee;}public void setPreSavingFee(Money preSavingFee) {
/*58*/ this.preSavingFee = preSavingFee;}public Money getTransferFee() {
/*62*/ return this.transferFee;}public void setTransferFee(Money transferFee) {
/*66*/ this.transferFee = transferFee;}public Map<String, BatchNoteInfoDTO> getNotedtos() {
/*70*/ return this.notedtos;}public void setNotedtos(Map<String, BatchNoteInfoDTO> notedtos) {
/*74*/ this.notedtos = notedtos;}public int getRowNum() {
/*78*/ return this.rowNum;}public void setRowNum(int rowNum) {
/*82*/ this.rowNum = rowNum;}}
如果类过大,反编译内容会很多,建议只反编译某个方法,例如
[arthas@10668]$
[arthas@10668]$ jad com.star.sms.service.support.GroupParamContainer getCustomer
Affect(row-cnt:0) cost in 37 ms.
No class found for: com.star.sms.service.support.GroupParamContainer
[arthas@10668]$ jad com.star.sms.business.customer.CustomerInfoService getCustomerClassLoader:
+-com.star.osgi.patch.classloader.BundlePatchURLClassLoader[stariboss-customer]+-org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@4089eba3[stariboss-customer:1.0.0(id=124)]+-org.eclipse.osgi.baseadaptor.BaseAdaptor$1@3983efa2Location:
/E:/Jboss/jboss-4.2.3-8.2.1R1-8091-liaoning_821-5g/server/default/./deploy/stariboss.war/tmp/.patchtmp/1671784240888/a_780108_server_22112201_DB-9505.stariboss-customer.jarprivate Customer getCustomer(CustomerInfoDTO result, Long certificateTypeId, String certificateNum, SubscriberResultDTO subscriberResultDTO) {Customer customer = new Customer();
/*730*/ if (this.getCustomerCodeGenerator() == null) {throw new MsrRuntimeException("customer.code.is.required", false, false, null);}
/*731*/ this.getCustomerCodeGenerator().generateAndSetCustomerCode(customer);
/*736*/ customer.setName(result.getCUST_NAME());
/*748*/ customer.setCertificate(this.getCertificate(result, certificateTypeId, certificateNum));
/*752*/ customer.setContactAddress("");
/*753*/ customer.setContactTel(result.getCONT_NUMBER());
/*755*/ customer.setEnrolDate(new Date());
/*758*/ customer.setMobileTel(result.getCONT_NUMBER());
/*760*/ customer.setCustomerAddress("");
/*762*/ customer.setSaleChannel((SaleChannel)ApplicationSessionHolder.getApplicationSession().getValue("currentSaleChannel"));
/*765*/ Sex sex = Sex.getByCode((String)result.getGENDER());
/*766*/ customer.setSex(sex == null ? Sex.MAN : sex);
/*769*/ customer.setStatus(CustomerStatus.EXISTING);
/*771*/ customer.setType(CustomerType.INDIVIDUAL);
/*773*/ SaleArea saleArea = this.getSaleAreaByGw(subscriberResultDTO.getCITY_CODE());
/*774*/ customer.setSaleArea(saleArea);
/*777*/ Address address = this.getAddress(saleArea.getId());
/*778*/ customer.setAddress(address);
/*779*/ customer.setContactMan(result.getCUST_NAME());
/*785*/ customer.setDetailAddressCode("");
/*796*/ customer.setRemark("createByGwInfo,");
/*797*/ return customer;}
4.方法调用路径,以及性能分析
trace 命令: 方法内部调用路径,并输出方法路径上的每个节点上耗时
例如: 查看GwPaymentService#callFeePay 调用路径和耗时
[arthas@10668]$ trace com.star.sms.business.payment.gw.GwPaymentService callFeePay
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 184 ms, listenerId: 3
`---ts=2022-12-26 13:37:22;thread_name=http-0.0.0.0-8091-1;id=9d;is_daemon=true;priority=5;TCCL=org.jboss.web.tomc`---[41.232898ms] com.star.sms.business.payment.gw.GwPaymentService:callFeePay()+---[0.020813ms] com.star.sms.business.payment.gw.helper.GwPaymentConverter:getInstance() #65+---[0.018817ms] com.star.sms.business.payment.gw.helper.GwPaymentConverter:callFeePayConvert() #65+---[0.019102ms] com.star.sms.gw.payment.GwPayDTO:getPayRecordId() #66`---[41.047583ms] com.star.sms.business.payment.gw.GwPaymentService:doPayFee() #66
trace 命令只会 trace 匹配到的函数里的子调用,并不会向下 trace 多层。因为 trace 是代价比较贵的
可以用正则表匹配路径上的多个类和函数,一定程度上达到多层 trace 的效果
例如: trace -E com.test.ClassA|org.test.ClassB method1|method2|method3
[arthas@13688]$ trace -E com.star.sms.business.provision.send.InstructionSender sendInstruction|sendGroupByGroup
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 2) cost in 218 ms, listenerId: 7
`---ts=2023-01-06 13:52:59;thread_name=http-0.0.0.0-8089-2;id=a2;is_daemon=true;priority=5;TCCL=org.jboss.web.tomcat.service.WebAppClassLoader@2c08c092`---[3.387799ms] com.star.sms.business.provision.send.InstructionSender:sendInstruction()+---[0.028225ms] org.springframework.util.CollectionUtils:isEmpty() #24+---[0.01397ms] com.star.sms.model.product.core.business.OpenDevice:getOpenDeviceType() #27+---[0.007413ms] com.star.sms.model.provision.enums.OpenDeviceType:name() #27+---[0.005987ms] com.star.sms.model.product.core.business.OpenDevice:getCode() #27+---[0.29422ms] org.apache.commons.logging.Log:info() #27+---[0.01511ms] com.star.sms.business.provision.send.util.InstructionGroupUtil:groupInstructionByServiceStr() #29+---[0.137417ms] com.star.sms.business.provision.send.InstructionSender:translate2Req() #30+---[2.620605ms] com.star.sms.business.provision.send.InstructionSender:sendGroupByGroup() #31| `---[2.603785ms] com.star.sms.business.provision.send.InstructionSender:sendGroupByGroup()| `---[2.538497ms] com.star.sms.business.provision.send.InstructionSender:sendOneGroupReq() #52+---[0.003421ms] com.star.sms.model.product.core.business.OpenDevice:getOpenDeviceType() #32+---[0.003136ms] com.star.sms.model.provision.enums.OpenDeviceType:name() #32+---[0.002851ms] com.star.sms.model.product.core.business.OpenDevice:getCode() #32`---[0.118885ms] org.apache.commons.logging.Log:info() #32
5.线上 debug
watch命令检测函数入参返回值,抛出异常等信息
参数说明、
- params : 表示所有参数数组 (因为不确定是几个参数)
- returnObject:表示返回值
- -b 方法调用之前观察
- -e 方法异常后观察
- -s 方法返回后观察
- -f 方法结束后观察
- -x 属性深度
例如:
watch com.star.sms.business.payment.gw.GwPayService payOrder returnObj 观察返回值
watch com.star.sms.business.payment.gw.GwPayService payOrder params 观察输入参数
watch com.star.sms.business.payment.gw.GwPayService payOrder "{params, returnObj}" -x 3
[arthas@10668]$ watch com.star.sms.business.payment.gw.GwPayService payOrder returnObj
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 694 ms, listenerId: 1
method=com.star.sms.business.payment.gw.GwPayService.payOrder location=AtExit
ts=2022-12-23 16:39:28; [cost=85.028278ms] result=@GwPayRecord[
serialVersionUID=@Long[6159375491528104642],
USER_ID=null,
groupNumber=null,
phoneNumber=@String[19200000078],
operationType=@GwPayOperaType[CALL_FEE_PAY],
payMethod=@DictionaryData[com.star.sms.model.system.basicparameter.DictionaryData@13d7],
payChannelType=@PayChannelType[SCAN_PAY],
payFee=@Money[锟? 10.00],
payDate=@Date[2022-12-23 00:00:00,000],
tradeNo=@String[202291392],
outTradeNo=@String[221223163927000244],
barCode=null,
buyerId=null,
thirdPayStatus=@PayStatus[SUCCESS],
bossPayStatus=@ScanPaymentSign[UNPAYED],
developOperator=null,
status=@Status[VALID],
acceptSheetId=null,
resp_code=@String[000000],
resp_desc=@String[璋冪敤鎴愬姛],
order_no=@String[12],
order_pay_status=@String[2],
pay_page_url=null,
scan_url=@String[http://www.baidu.com],
sign_info=@String[hhggr],
business_id=null,
gw_pos_trade_no=null,
prov_mer_order_no=null,
posPayStatus=null,
posRespDesc=null,
payNo=@String[13214],
id=@Long[893],
name=null,
createDate=@Timestamp[2022-12-23 16:39:27,292],
modifyDate=@Timestamp[2022-12-23 16:39:28,000],
createOperator=@Operator[com.star.sms.model.system.organization.Operator@5d],
modifyOperator=@Operator[com.star.sms.model.system.organization.Operator@5d],
remark=null,
operationTerminal=@Terminal[com.star.sms.model.system.organization.Terminal@2d660cb5],
operationSpot=@SaleChannel[com.star.sms.model.system.organization.SaleChannel@9],
version=@Integer[0],
]
[arthas@10668]$
[arthas@10668]$ watch com.star.sms.business.payment.gw.GwPayService payOrder "{params, returnObj}" -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 129 ms, listenerId: 4
method=com.star.sms.business.payment.gw.GwPayService.payOrder location=AtExit
ts=2022-12-26 13:56:10; [cost=43.709849ms] result=@ArrayList[@Object[][@GwPayRecord[serialVersionUID=@Long[6159375491528104642],USER_ID=null,groupNumber=null,phoneNumber=@String[19200007899],operationType=@GwPayOperaType[CALL_FEE_PAY],payMethod=@DictionaryData[com.star.sms.model.system.basicparameter.DictionaryData@13d7],payChannelType=@PayChannelType[SCAN_PAY],payFee=@Money[锟? 99.00],payDate=@Date[2022-12-26 00:00:00,000],tradeNo=@String[202299042],outTradeNo=@String[221226135609002605],barCode=null,buyerId=null,thirdPayStatus=@PayStatus[SUCCESS],bossPayStatus=@ScanPaymentSign[UNPAYED],developOperator=null,status=@Status[VALID],acceptSheetId=null,resp_code=@String[000000],resp_desc=@String[璋冪敤鎴愬姛],order_no=@String[12],order_pay_status=@String[2],pay_page_url=null,scan_url=@String[http://www.baidu.com],sign_info=@String[hhggr],business_id=null,gw_pos_trade_no=null,prov_mer_order_no=null,posPayStatus=null,posRespDesc=null,payNo=@String[13214],id=@Long[898],name=null,createDate=@Timestamp[2022-12-26 13:56:09,981],modifyDate=@Timestamp[2022-12-26 13:56:10,000],createOperator=@Operator[com.star.sms.model.system.organization.Operator@5d],modifyOperator=@Operator[com.star.sms.model.system.organization.Operator@5d],remark=@String[TRACE TEST],operationTerminal=@Terminal[com.star.sms.model.system.organization.Terminal@7a05dcd9],operationSpot=@SaleChannel[com.star.sms.model.system.organization.SaleChannel@9],version=@Integer[0],],],@GwPayRecord[serialVersionUID=@Long[6159375491528104642],USER_ID=null,groupNumber=null,phoneNumber=@String[19200007899],operationType=@GwPayOperaType[CALL_FEE_PAY=@GwPayOperaType[CALL_FEE_PAY],BUSINESS_PAY=@GwPayOperaType[BUSINESS_PAY],DAMAGES_PAY=@GwPayOperaType[DAMAGES_PAY],$VALUES=@GwPayOperaType[][isEmpty=false;size=3],name=@String[CALL_FEE_PAY],ordinal=@Integer[0],],payMethod=@DictionaryData[serialVersionUID=@Long[4048790182402733107],code=@String[2800],displayPos=@Integer[0],type=@DictionaryDataType[com.star.sms.model.system.basicparameter.DictionaryDataType@1b5b],status=@Status[VALID],operateLevel=null,saleAreas=null,synchronizeStatus=@SynchronizeStatus[UNSYNCHRONIZED],synchronizedt=null,gw5GCorpOrgCode=null,regionID=null,regionExtId=null,id=@Long[5079],name=@String[鐜伴噾鏀粯],createDate=@Timestamp[2022-03-30 12:13:49,000],modifyDate=null,createOperator=@Operator[com.star.sms.model.system.organization.Operator@710107e1],modifyOperator=@Operator[com.star.sms.model.system.organization.Operator@7aac7ebc],remark=null,operationTerminal=@Terminal[com.star.sms.model.system.organization.Terminal@52b4a78f],operationSpot=@SaleChannel[com.star.sms.model.system.organization.SaleChannel@5264c7b4],version=@Integer[0],],payChannelType=@PayChannelType[CARD_SWIP=@PayChannelType[CARD_SWIP],SCAN_PAY=@PayChannelType[SCAN_PAY],$VALUES=@PayChannelType[][isEmpty=false;size=2],name=@String[SCAN_PAY],ordinal=@Integer[1],],payFee=@Money[MOVE_CODE=@Integer[32],serialVersionUID=@Long[3256444694312726840],CENTS=@int[][isEmpty=false;size=4],HanDigiStr=@String[][isEmpty=false;size=10],HanDiviStr=@String[][isEmpty=false;size=24],ZERO=@Money[锟? 0.00],CURRENCY_SYMBOL_POSTFIX=@String[ ],amount=@Long[9900],currency=@Currency[CNY],currentCurrency=@Currency[CNY],],payDate=@Date[2022-12-26 00:00:00,000],tradeNo=@String[202299042],outTradeNo=@String[221226135609002605],barCode=null,buyerId=null,thirdPayStatus=@PayStatus[SUCCESS=@PayStatus[SUCCESS],FAIL=@PayStatus[FAIL],UNKOWN=@PayStatus[UNKOWN],CANCEL=@PayStatus[CANCEL],NOTPAY=@PayStatus[NOTPAY],$VALUES=@PayStatus[][isEmpty=false;size=5],name=@String[SUCCESS],ordinal=@Integer[0],],bossPayStatus=@ScanPaymentSign[UNPAYED=@ScanPaymentSign[UNPAYED],PAYED=@ScanPaymentSign[PAYED],$VALUES=@ScanPaymentSign[][isEmpty=false;size=2],name=@String[UNPAYED],ordinal=@Integer[0],],developOperator=null,status=@Status[INVALID=@Status[INVALID],VALID=@Status[VALID],$VALUES=@Status[][isEmpty=false;size=2],name=@String[VALID],ordinal=@Integer[1],],acceptSheetId=null,resp_code=@String[000000],resp_desc=@String[璋冪敤鎴愬姛],order_no=@String[12],order_pay_status=@String[2],pay_page_url=null,scan_url=@String[http://www.baidu.com],sign_info=@String[hhggr],business_id=null,gw_pos_trade_no=null,prov_mer_order_no=null,posPayStatus=null,posRespDesc=null,payNo=@String[13214],id=@Long[898],name=null,createDate=@Timestamp[2022-12-26 13:56:09,981],modifyDate=@Timestamp[2022-12-26 13:56:10,000],createOperator=@Operator[PROPERTY_USERNAME=@String[code],PROPERTY_PASSWORD=@String[password],DYNAMIC_PASSWORD=@String[dynamicPassword],serialVersionUID=@Long[3256443599062578999],code=@String[0147],password=null,dynamicPassword=null,type=@OperatorType[COMMON_OP],tel=null,familyAddress=null,email=null,validDateRange=null,sex=null,identityCard=null,education=null,department=@Department[com.star.sms.model.system.organization.Department@3],level=@OperationLevel[com.star.sms.model.system.privilege.OperationLevel@1],address=@Address[com.star.sms.model.system.resource.Address@1],rayNode=null,saleAreas=@ArrayList[isEmpty=false;size=13],roles=@ArrayList[isEmpty=false;size=16],saleChannels=@ArrayList[isEmpty=false;size=15],channelBindings=@ArrayList[isEmpty=false;size=15],segment=null,synchronizeStatus=null,synchronizedt=null,gw5GOperCode=@String[OPER0001],storeHouses=null,terminals=null,mustBindTerminal=@Boolean[false],status=null,selectedSaleChannel=null,dynamicPasswordCheck=null,isVIPOperator=@Boolean[false],passwordLastModifyDate=@Date[2021-11-02 00:00:00,000],imei=null,jobType=null,id=@Long[93],name=@String[huangzw],createDate=null,modifyDate=null,createOperator=null,modifyOperator=null,remark=null,operationTerminal=null,operationSpot=null,version=@Integer[0],],//略version=@Integer[0],],
]
上一篇:如何使用CURL工具及简单介绍
如何使用监控诊断工具Arthas(阿尔萨斯)相关推荐
- Arthas : 在线分析诊断工具Arthas(阿尔萨斯)
1.美图 2.背景 想学JDK自带的工具,BTrace然后,同事说这个过时了,但是我不是很相信,因为是JDK自带的工具,他推荐这个,于是我就来看看这个到底是什么东西. Arthas 是Alibaba开 ...
- 阿里重磅开源在线分析诊断工具Arthas(阿尔萨斯)
github地址: Arthas English version goes here. Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似问题而束手无策时,Art ...
- arthas 查看哪个方法调用最耗时_Java开源诊断工具Arthas使用方法详解
一.前言 1.热更新代码的场景 (1)当线上服务器出现问题时,有些时候现有的手段不足以发现问题所在,可能需要追加打印日志或者增加一些调试代码,如果我们去改代码重新部署,会破坏问题现场,可以通过热部署的 ...
- Java-JVM诊断工具Arthas
Java-JVM诊断工具Arthas https://arthas.aliyun.com/doc/ 官网 介绍 Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱. 当你遇到以下类似 ...
- linux下检测硬盘,【转载】linux下硬盘监控诊断工具SmartTools
对于windwos下raid卡具备告警功能,当硬盘故障.raid卡告警时,可以发邮件给管理员.IBM.HP.Dell都支持.但在linux下,就没有找到相关的好工具了,今天到陈沙克的博客上到一篇关于l ...
- Java诊断工具-Arthas入门与实践
Java诊断工具-Arthas入门与实践 目录 Java诊断工具-Arthas入门与实践 什么是Arthas? Arthas能做什么? 我在哪里可以下载Arthas? 快速入门 1. 下载并运行mat ...
- 阿里Java诊断工具 arthas - 生产环境反编译动态修改程序调试应用
阿里Java诊断工具 arthas - 生产环境反编译动态修改程序调试应用 一.arthas 上篇文章我们借助arthas监测线上系统的运行信息.排查程序运行缓慢问题,尽管这样已经非常好了,但是还是会 ...
- java诊断神器 arthas(阿尔萨斯)
java诊断神器 arthas(阿尔萨斯) 官网地址:https://arthas.aliyun.com/doc/en/index.html 1.快速开始 1.1.windows版本安装 # 命令行输 ...
- 阿里开源的Java诊断工具——Arthas
文章目录 1 问题背景 2 前言 3 Arthas有什么作用 4 入门小实践 5 SpringBoot应用.Arthas.Arthas Tunnel Server之间的关系 1 问题背景 线上生产环境 ...
最新文章
- GitHub 的项目徽章
- 分享30个激励的非营利网站设计精美案例
- 深度聚焦 3 大技术领域,阿里云将重磅亮相首届线上 KubeCon
- cmake 编译安装方法
- mutex_lock
- 实例5:python
- 一定质量的封闭气体被压缩后_多晶硅氯氢化装置补充氢隔膜压缩机十字头铜套磨损原因分析与改善探讨...
- C#LeetCode刷题之#167-两数之和 II - 输入有序数组(Two Sum II - Input array is sorted)
- 云原生的本质_云原生2.0的逻辑之辩,如何让每个企业都成为新云原生企业
- 【开源毕设】一款精美的家校互动APP分享——爱吖校推 [你关注的,我们才推](持续开源更新2)...
- [USACO DEC13] 名称记录
- ecshop一键购物
- mysql fixed数据类型_MySQL数据类型有哪些?MySQL数据类型详解
- 被发哥拉着跪向观众,朱军为何如此惊魂?
- 新书已经到手《Java程序员,上班那点事儿》正式销售纪念帖
- 【我的Android进阶之旅】 高效的设计稿标注及测量工具Markman介绍
- 电商RPA:直播行业必不可少的工具
- Flutter Provider状态管理-Consumer
- 隐藏控件--HiddenField控件
- Matlab Fmincon 解决带积分的二元非线性规划问题