应用场景
线上出问题,无法增加日志、无法线上调试,需要实现切面功能
Java应用服务在生产环境中可能会出现各种各样的问题,有些问题在找到根本原因之前看似“不可思议”,有时并没有产生异常或者错误消息,这时我们无法根据已有的日志来定位问题,那么我们需要更多的信息如参数、返回值、程序逻辑判断、循环次数等来追踪问题。如果临时增加日志,则需要重新上线,成本较高,使用远程调试又会影响线上流量导致客户程序超时,这时btrace应运而生。btrace可以动态的跟踪Java运行时程序,将定制化的跟踪字节码切面注入运行类中,对运行代码无侵入,对性能的影响也可忽略不计。
使用方法
btrace [-p port] [-cp classpath] pid btrace-script
参数解析
- port:指定btrace agent的服务端监听端口号,供客户端连接。
- classpath:用于指定依赖的类加载路径。
- pid:表示进程号,可通过jps或者ps命令获取。
- btrace-script:btrace跟踪切面脚本。
在运行命令之前,我们需要编写btrace的跟踪脚本:
import java.util.Date;
import com.sun.btrace.BTraceUtils;
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
@BTrace
public class Btrace {
@OnMethod(class="com.cloudate.controller.AdminController",
method="sayHello",
location=@Location(Kind.RETURN))
public static void sayHello() { // 单位是ns,要转为ms
println(strcat("duration(ms):", str(duration/1000000)));
}
}
这个跟踪脚本对业务代码的方法进行了拦截,并打印方法的执行时间:
public class AdminController {
public String sayHello(String name, int age) {
return "hello everyone";
}
}
使用示例
btrace -p 2020 -cp ~/servlet-api.jar 1507 ~/BTrace.java
AdminController类的sayHello被调用时,控制台就会打印方法的执行时间,这对定位线上的棘手问题有非常大的帮助。