软件测试

arthas 线上运维学习笔记

2020-05-31  本文已影响0人  不加糖的开水

安装

快速安装

使用as.sh安装

全量安装

点击下载

卸载

启动

java -jar arthas-boot.jar --target-ip 0.0.0.0
1563721331455.png

使用技巧

退出

常用命令

dashboard

数据说明:

thread

1563721533844.png
*   在该命令中,arthas 会停顿5秒,进行计算得出结果,为阿里点赞

jvm

sc

sc javax.servlet.Filter

-d 参数可以打印出类加载的具体信息,方便定位类加载问题

sc 支持通配符,比如搜索所有的 StringUtils

Copysc *StringUtils

[图片上传失败...(image-2b1ed8-1590935866588)]

打印类的 Field 信息:

Copysc -d -f demo.MathGame

sm

sm java.lang.String
1563722348451.png
sm java.lang.String toString
1563722440683.png
sm -d java.math.RoundingMode
1563722486838.png

jad

参数名称 参数说明
class-pattern 类名表达式匹配
[c:] 类所属 ClassLoader 的 hashcode
[E] 开启正则表达式匹配,默认为通配符匹配
jad demo.MatthGame
$ jad com.platform.controller.SysConfigController

ClassLoader:
+-WebappClassLoader
    context: /platform
    delegate: false
    repositories:
      /WEB-INF/classes/
  ----------> Parent Classloader:
  java.net.URLClassLoader@2d127a61

  +-java.net.URLClassLoader@2d127a61
    +-sun.misc.Launcher$AppClassLoader@18b4aac2
      +-sun.misc.Launcher$ExtClassLoader@6dde5c8c

Location:
/H:/Development/ideaworkspace/platform/platform-framework/target/platform-framework/WEB-INF/classes/

/*
 * Decompiled with CFR 0_132.
 *
 * Could not load the following classes:
 *  com.platform.annotation.SysLog
 *  com.platform.controller.AbstractController
 *  com.platform.entity.SysConfigEntity
 *  com.platform.service.SysConfigService
 *  com.platform.utils.PageUtils
 *  com.platform.utils.Query
 *  com.platform.utils.R
 *  com.platform.validator.ValidatorUtils
 *  org.apache.shiro.authz.annotation.RequiresPermissions
 *  org.springframework.beans.factory.annotation.Autowired
 *  org.springframework.web.bind.annotation.PathVariable
 *  org.springframework.web.bind.annotation.RequestBody
 *  org.springframework.web.bind.annotation.RequestMapping
 *  org.springframework.web.bind.annotation.RequestParam
 *  org.springframework.web.bind.annotation.RestController
 */
package com.platform.controller;

import com.platform.annotation.SysLog;
import com.platform.controller.AbstractController;
import com.platform.entity.SysConfigEntity;
import com.platform.service.SysConfigService;
import com.platform.utils.PageUtils;
import com.platform.utils.Query;
import com.platform.utils.R;
import com.platform.validator.ValidatorUtils;
import java.util.List;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value={"/sys/config"})
public class SysConfigController
extends AbstractController {
    @Autowired
    private SysConfigService sysConfigService;

    @RequestMapping(value={"/list"})
    @RequiresPermissions(value={"sys:config:list"})
    public R list(@RequestParam Map<String, Object> params) {
        Query query = new Query(params);
        List configList = this.sysConfigService.queryList((Map)query);
        int total = this.sysConfigService.queryTotal((Map)query);
        PageUtils pageUtil = new PageUtils(configList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", (Object)pageUtil);
    }

    @RequestMapping(value={"/info/{id}"})
    @RequiresPermissions(value={"sys:config:info"})
    public R info(@PathVariable(value="id") Long id) {
        SysConfigEntity config = this.sysConfigService.queryObject(id);
        return R.ok().put("config", (Object)config);
    }

    @SysLog(value="\u4fdd\u5b58\u914d\u7f6e")
    @RequestMapping(value={"/save"})
    @RequiresPermissions(value={"sys:config:save"})
    public R save(@RequestBody SysConfigEntity config) {
        ValidatorUtils.validateEntity((Object)config, (Class[])new Class[0]);
        this.sysConfigService.save(config);
        return R.ok();
    }

    @SysLog(value="\u4fee\u6539\u914d\u7f6e")
    @RequestMapping(value={"/update"})
    @RequiresPermissions(value={"sys:config:update"})
    public R update(@RequestBody SysConfigEntity config) {
        ValidatorUtils.validateEntity((Object)config, (Class[])new Class[0]);
        this.sysConfigService.update(config);
        return R.ok();
    }

    @SysLog(value="\u5220\u9664\u914d\u7f6e")
    @RequestMapping(value={"/delete"})
    @RequiresPermissions(value={"sys:config:delete"})
    public R delete(@RequestBody Long[] ids) {
        this.sysConfigService.deleteBatch(ids);
        return R.ok();
    }
}

mc

redefine

monitor

trace

watch

watch 命令可以查看函数的:

Copywatch demo.MathGame primeFactors returnObj

[图片上传失败...(image-c6fd81-1590935866588)]

Copywatch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2
  1. 第一个参数是类名,支持通配
  2. 第二个参数是函数名,支持通配
  3. 第三个参数是定义返回值
  4. -x 2 是为了将结果展开

返回值表达式实际是一个 ognl 表示,支持一些内置对象:

watch命令支持按请求耗时进行过滤:

watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'

Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码


ognl

获取静态类的静态字段:

ognl '@demo.MathGame@random'

具体,查看执行ognl表达式

trace

方法内部调用路径,并输出方法路径上的每个节点上耗时

trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路

参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
condition-express 条件表达式
[E] 开启正则表达式匹配,默认为通配符匹配
[n:] 命令执行次数
#cost 方法执行耗时

很多时候我们只想看到某个方法的 rt 大于某个时间之后的 trace 结果,现在 Arthas 可以按照方法执行的耗时来进行过滤了,例如 trace *StringUtils isBlank '#cost>100' 表示当执行时间超过 100ms 的时候,才会输出 trace 的结果。

watch/stack/trace 这个三个命令都支持 #cost

trace 函数:

$ trace demo.MathGame run
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 42 ms.
`---ts=2018-12-04 00:44:17;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[10.611029ms] demo.MathGame:run()
        +---[0.05638ms] java.util.Random:nextInt()
        +---[10.036885ms] demo.MathGame:primeFactors()
        `---[0.170316ms] demo.MathGame:print()

过滤掉 jdk 的函数:

$ trace -j  demo.MathGame run
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 31 ms.
`---ts=2018-12-04 01:09:14;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[5.190646ms] demo.MathGame:run()
        +---[4.465779ms] demo.MathGame:primeFactors()
        `---[0.375324ms] demo.MathGame:print()

trace 在执行的过程中本身是会有一定的性能开销,在统计的报告中并未像 JProfiler 一样预先减去其自身的统计开销

stack

输出当前方法被调用的调用路径

很多时候我们都知道一个方法被执行,但这个方法被执行的路径非常多,或者你根本就不知道这个方法是从那里被执行了,此时你需要的是 stack 命令。

参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
condition-express 条件表达式
[E] 开启正则表达式匹配,默认为通配符匹配
[n:] 执行次数限制

据执行时间来过滤:

$ stack demo.MathGame primeFactors '#cost>5'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 35 ms.
ts=2018-12-04 01:35:58;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    @demo.MathGame.run()
        at demo.MathGame.main(MathGame.java:16)

实战

启动 Spring Boot Demo

wget https://github.com/hengyunabc/katacoda-scenarios/raw/master/demo-arthas-spring-boot.jar
java -jar demo-arthas-spring-boot.jar

启动 arthas-boot

wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar --target-ip 0.0.0.0

就像基础教程说过的,选择目标进程

查看 JVM 信息

sysprop

[图片上传失败...(image-51b975-1590935866588)]

sysenv

[图片上传失败...(image-e209dc-1590935866588)]

分析线程阻塞

不重启修复BUG

参考

上一篇 下一篇

猜你喜欢

热点阅读