一、前言
一套系统是否稳定运行,取决于它的运行健康度,而这包括;调用量、可用率、响应时长以及服务器性能等各项指标的一个综合值。并且在系统出现异常问题时,可以抓取整个业务方法执行链路并输出;当时的入参、出参、异常信息等等。当然还包括一些JVM、Redis、Mysql的各项性能指标,以用于快速定位并解决问题。
那么要做到这样的事情有什么监控方案呢,这里面的做法比较多。比如:
:::info
- 最简单粗暴的可能就是硬编码在方法中,收取执行耗时以及出入参和异常信息。但这样的成本实在太大,而且有一些不可预估的风险。
- 可以选择切面方式做一套统一监控的组件,相对来说还是好一些的。但也需要硬编码,同时维护成本不低。
- 市面上对于这样的监控其实是有整套的非入侵监控方案的,比如;
Google Dapper
、Zipkin
等都可以实现,他们都是基于探针技术非入侵的采用字节码增强的方式进行监控。 :::
那么这样非入侵的探针方式是怎么实现的呢?如何去做方法的字节码增强
?
在字节码增强方面有三个框架;ASM
、Javassist
、ByteCode
,各有优缺点按需选择。这在我们之前的字节码编程文章里也有所提到。本文主要讲解关于 ASM
方式的字节码增强,接下来的案例会逐步讲解一个给方法添加 TryCatch
块,用于采集异常信息以及正常的出参结果的流程。
二、系统环境
- jdk1.8.0
- asm-commons 6.2.1
三、技术目标
通过 ASM
字节码增强技术,使用指令码将方法修改为我们想要的效果。这部分原本需要使用 JavaAgent
技术,在工程启动加载时候进行修改字节码。这里为了将关于字节码核心内容展示出来,通过加载类名称获取字节码进行修改。
修改之前的代码:
public Integer strToNumber(String str) {
return Integer.parseInt(str);
}
使用ASM技术修改之后的代码:
public Integer strToNumber(String str) {
try {
Integer var2 = Integer.parseInt(str);
MethodTest.point("org.itstack.test.MethodTest$Test.strToNumber", var2);
return var2;
} catch (Exception var3) {
MethodTest.point("org.itstack.test.MethodTest$Test.strToNumber", var3);
throw var3;
}}
从修改前到修改后,可以看到。有如下几点修改;
- 返回值赋值给新的参数,并做了输出
- 把方法包裹在一个
TryCatch
中,并将异常也做了输出
好!如果你有很敏锐的嗅觉,或者很多小问号。那么你是否会想到如果使用到你自己的业务中,是不是就可以做一套非入侵的监控系统了?
四、实现过程
字节码增强的过程乍一看还是比较麻烦的,如果你没有阅读过JVM虚拟机规范等相关书籍,确实很不好理解。但是也就是这部分不那么容易理解的知识,才是你后续价值的体现。