下载 Arthas
arthas-boot方式(官方推荐方式)
curl -O https://arthas.aliyun.com/arthas-boot.jar
原理分析:
- 此方式是启动一个进程,使用的是VirtualMachine.attach()技术粘附在指定的可选的java进程中的。
- 想用Arthas的时候,attach到指定进程,通过Instrumentation来拦截所有的字节码;
- 如果你的机器启动了很多个java进程,根据进程号进入到目标应用去使用
- 不用就退出,对平时没有使用的时候是没有任何性能损耗的,只有用的时候才会额外有资源耗损。
监测目标程序
# 运行方式1,先运行,在选择 Java 进程 PID
java -jar arthas-boot.jar
# 选择进程(输入[]内编号(不是PID)回车)
[INFO] arthas-boot version: 3.5.0
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 8260 cn.wanda.wic.content.manager.WicContentManager
[2]: 22276 org.apache.catalina.startup.Bootstrap
[3]: 9095 com.sinovatech.rd.brand.schedule.ScheduleMain
[4]: 3546 cn.wanda.wic.content.job.WicContentJob
[5]: 10764 cn.wanda.wic.content.admin.WicContentAdmin
[6]: 9743 org.apache.catalina.startup.Bootstrap
# 运行方式2,运行时选择 Java 进程 PID
java -jar arthas-boot.jar [PID]
查询接口耗时
trace 全路径类名 方法名 -n 10 --skipJDKMethod false
全路径类名
:慢接口所在的类的全路径名。方法名
:慢接口的方法名。-n
:表示跟踪次数,这里表示跟踪10次。--skipJDKMethod false
:表示不跳过JDK内置的方法,有时候慢接口问题可能出现在JDK的方法中。
案例:
trace cn.wanda.wic.content.admin.api.shop.BackgroundShopApi queryNewShopList
相当于调起了一个监听程序,然后通过页面或者 apipost 调用一次就可以查看结果
[arthas@10764]$ trace cn.wanda.wic.content.admin.api.shop.BackgroundShopApi queryNewShopList
Press Q or Ctrl+C to abort.
Affect(class count: 3 , method count: 2) cost in 347 ms, listenerId: 1
`---ts=2024-09-23 20:43:55.381;thread_name=http-nio-10100-exec-5;id=205;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@620260ad
`---[4832.525895ms] cn.wanda.wic.content.admin.service.shop.api.BackgroundShopApiImpl$$EnhancerBySpringCGLIB$$71a787fb:queryNewShopList()
`---[99.99% 4832.146341ms ] org.springframework.cglib.proxy.MethodInterceptor:intercept()
`---[98.54% 4761.696122ms ] cn.wanda.wic.content.admin.service.shop.api.BackgroundShopApiImpl:queryNewShopList()
+---[0.00% 0.034505ms ] ai.lamb.framework.starter.data.request.PageRequest:getData() #216
+---[0.00% 0.17538ms ] ai.lamb.framework.starter.common.util.BeanUtil:copy() #218
+---[0.00% 0.012484ms ] cn.wanda.wic.content.orm.mybatis.param.shop.BackgroundShopQueryAllParam:setIsNew() #219
+---[0.00% 0.014046ms ] cn.wanda.wic.content.orm.mybatis.param.MerutilManualProjectListParam:builder() #222
+---[0.00% 0.008807ms ] cn.wanda.wic.content.admin.enums.YesOrNoEnum:getCode() #222
+---[0.00% 0.012012ms ] cn.wanda.wic.content.orm.mybatis.param.MerutilManualProjectListParam$MerutilManualProjectListParamBuilder:isApproveList() #222
+---[0.00% 0.010651ms ] cn.wanda.wic.content.orm.mybatis.param.MerutilManualProjectListParam$MerutilManualProjectListParamBuilder:build() #222
+---[1.60% 76.071634ms ] cn.wanda.wic.content.admin.service.merutil.business.MerutilManualService:listProjectByOrg() #222
+---[0.00% 0.019857ms ] org.springframework.util.CollectionUtils:isEmpty() #223
+---[0.00% 0.014948ms ] cn.wanda.wic.content.orm.mybatis.param.shop.BackgroundShopQueryAllParam:setPermissionList() #226
+---[0.00% min=0.00546ms,max=0.009879ms,total=0.015339ms,count=2] ai.lamb.framework.starter.data.request.PageRequest:getPageParam() #229
+---[0.00% 0.012634ms ] ai.lamb.framework.starter.data.page.PageParam:getPageNum() #229
+---[0.00% 0.007754ms ] ai.lamb.framework.starter.data.page.PageParam:getPageSize() #229
+---[0.00% 0.018995ms ] com.github.pagehelper.PageHelper:startPage() #229
+---[98.16% 4674.112236ms ] com.github.pagehelper.Page:doSelectPageInfo() #229
+---[0.00% 0.054803ms ] com.github.pagehelper.PageInfo:getList() #231
+---[0.15% 7.118508ms ] cn.wanda.wic.content.admin.service.shop.api.BackgroundShopApiImpl:getBackgroundShopQueryAllVOList() #231
+---[0.00% 0.215677ms ] ai.lamb.framework.starter.common.util.BeanUtil:copyList() #231
+---[0.00% 0.012904ms ] com.github.pagehelper.PageInfo:getTotal() #231
`---[0.00% 0.018555ms ] ai.lamb.framework.starter.data.response.PageResponse:page() #231
很明显,大概率是sql问题,就需要进行sql调优