Java不停机监控&热操作


theme: geek-black

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

Java不停机监控&热操作

引言

在使用Arthas的过程中,感觉有些功能很好用,但是命令行的用起来会比较麻烦,,本着学习的态度,自己设计了一套无需停机,埋点,热修复,监控等功能的应用,并提供了WEB页面进行操作,并且会不断集成一些常用的功能 .

### 1. 已经支持的操作 - 监控JVM、GC、启动参数、线程、系统参数等大盘信息 - 对于正在运行中的程序,动态给某个方法织入代码,获取某个函数的执行时间 - 对于正在运行中的程序,动态给某个方法织入代码, 获取某个controller方法请求参数和返回值 - 对于正在运行中的程序,获取全部线程占有CPU时间百分比,并支持查看指定线程运行的堆栈信息 - 热修复,通过反编译导出java文件,修改后再导入通过classload重载入实现热编译(适用于空指针等bug,少量修改代码就可解决问题时使用) - 由于使用web页面操作,ip需要改为目标进程机器ip(默认是localhost如果是本地运行无需修改)

关键技术

|技术名称| 作用 | |--|--| | Javaagent | 在运行前加载,或在运行中对字节码进行操作 | | VirtualMachine | 在运行中附着到目标进程上,并调用agent |

架构部分 | 工程 | 技术 | |--|--| | web | Vue + Ant design | | server |Springboot+Websocket(以后可能弃用Springboot改为NettyServer)| | agent |netty + Javassist + cfr + JavaCompiler|

2. 如何安装使用?

  1. 去阿里云Maven仓库下载Jar包即可 (maven默认国外仓库)

(阿里云Maven仓库) 推荐使用!

Github源码

搜索nobugboy或ETrace即可

image.png

获取到下载地址,他这个链接会动态刷新,所以需要自己去搜索下再下载。

image.png

  1. 获取到连接后 ```
  2. win直接点击连接下载,mac/linux wget连接
  3. 将文件改名为 ETrace-1.2.4.jar (点连接下载不用改) ```

  4. 运行 linux/macos 具体由你配置的环境变量名称作为值,一般为$JAVA_HOME windows $JAVA_HOME直接替换为javahome的绝对目录即可 java -jar -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar ETrace-1.2.4.jar

  5. 默认用户名 admin 密码 admin123

3. gif演示操作

  1. 演示大盘和线程追踪,点击线程直接可以获取当前堆栈信息(定位高CPU原因)

etrace操作1.gif

  1. 演示织入打印执行时间(为了好看我睡眠了1s)

时间打印.gif

  1. 演示织入打印参数返回值

aop.gif

4. 热修复,这个功能录制太繁琐,直接图文吧

场景:一个同学提交了空指针异常的代码到了生产环境,测试没有覆盖到。

``` @GetMapping(value = "/get/{id}",name = "根据id获取用户") public User test(@PathVariable(value = "id",name = "id") String id){ User user = null; user.setName("测试"); return user; } #调用一下试试

curl localhost:8080/get/1

出错了! exception is java.lang.NullPointerException at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-5.3.6.jar:5.3.6] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.6.jar:5.3.6] ``` 此时服务已经在运行状态,在不能重启服务的情况下我们来修复,先将需要修改的类路径找到,输出到桌面(输出路径一定要在最后加 /)

image.png

image.png

image.png 修改空指针问题,编辑导出的文件 ```

/* * Decompiled with CFR. * * Could not load the following classes: * com.example.springboottestdemo.controller.User */ package com.example.springboottestdemo.controller;

import com.example.springboottestdemo.controller.User; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController;

@RestController(value="\u7528\u6237\u76f8\u5173\u63a5\u53e3") public class TestController { @GetMapping(value={"/last"}, name="get\u8bf7\u6c42\u6d4b\u8bd5\u53c2\u6570\u63cf\u8ff0") public User test2(User user) { return user; }

@PostMapping(value={"/post"}, name="post\u8bf7\u6c42\u6d4b\u8bd5\u53c2\u6570\u63cf\u8ff0")
public User test1(@RequestBody User user) {
    System.out.println((Object)user);
    return user;
}

@GetMapping(value={"/get/{id}"}, name="\u6839\u636eid\u83b7\u53d6\u7528\u6237")
public User test(@PathVariable(value="id", name="id") String id) {
    //将此处修复
    User user = new User();
    user.setName("\u6d4b\u8bd5");
    return user;
}

} ```

image.png

image.png

看到控制台 "compiler ok"字样代表编译完成,接下来重新load进去

image.png

看到控制台 "redefine successful !"字样代表load成功,此时我们再次请求刚才报错的接口,错误消失代表成功修复。 curl localhost:8080/get/1 {"id":null,"name":"测试","us":null,"type":null}%

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值