大家好,我是烤鸭:
    最近一直在研究全链路追踪,比如cat、skywalking、zipkin等。
    发现 skywalking 是基于bytebuddy 实现的,想自己试着写一下demo。
    demo的git地址,感兴趣的可以自己试下。代码在idea中可以跑,至于其他场景需要自己研究(比如用cmd或者linux可能会报NoClassDefDoundError)。

demo地址:(仅实现了http方式的链路,有需要的可以自己补充,比如dubbo或者其他rpc方式的拦截)

https://gitee.com/fireduck_admin/link-trace-demo
    环境:
    JDK 8

1.    设计目标

监控接口(方法)耗时和链路关系(http请求),对比aop方式,zipkin和cat 是基于拦截的形式。

2.  bytebuddy

bytebuddy网上资料虽然不多,但是api比较简单,看看基本就会了。我也不介绍了。具体想看的去官网看下吧。
    https://bytebuddy.net/

3.  接口耗时伪代码说明

由于测试链路,我们需要一个agent项目和demo项目(用于请求转发)。
    agent项目创建拦截和写具体的拦截逻辑,这里以 拦截 Spring的service注解为例。这是在agent项目里的。

public static void premain(String agentArgs, Instrumentation inst) {System.out.println("==============Client=============== premain =============start============");AgentBuilder.Transformer transformerService = new AgentBuilder.Transformer() {@Overridepublic DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {return builder.method(ElementMatchers.<MethodDescription>any()) // 拦截任意方法.intercept(MethodDelegation.to(MyServiceAdvice.class)); // 委托}};// 拦截 ServiceAgentBuilder agentBuilder = agentBuilder.type(ElementMatchers.isAnnotatedWith(ElementMatchers.named("org.springframework.stereotype.Service"))) // 指定需要拦截的类.transform(transformerService);// 注入 instagentBuilder.installOn(inst);System.out.println("================Client============ premain ================finish===========");}

demo项目启动的时候需要在idea配置vm参数。不知道怎么配的看图。

 -javaagent:\xx\xx\target\link-trace-demo-agent-1.0-SNAPSHOT.jar

拦截效果如图,这样就实现了接口(方法)调用的耗时统计。

4.  全链路伪代码说明

其实自从google在2010年提出了dapper论文后,后续的链路追踪基本都是按照这个思路来实现的,我这就是简易版。
    agent拦截 controller 注解跟上面的service类似,就不贴代码了。
    这里我们需要一个span对象,当前的请求信息记录在span对象(主要是谁调的你),并且放到threadlocal的调用堆栈中,这样当前的请求和线程就绑定了(方便单个服务内的流转,比如controller调service)。
    这里截图可以看下只单独拦截了web,由于没有上游的信息,所以生成的新的span,seq为1。如图。

模拟下拦截web后调用web方法的链路信息。如图所示。pid(parentid)指的是上个链路的id,这样就可以获取到整个调用链的完整信息(出入参、时间、方法等)


    再多链路,比如web-service-web或者更多服务的自己试下吧,思路就是这样的。

5.  aop个agent的对比

只是单纯的统计aop方式和bytebuddy两种方式。aop底层有接口使用jdk 代理,无接口使用cglib(底层asm)。而bytebuddy底层也是 asm
    先放一张官方的对比图。

至于到底快不快,我试下。先链路的代码先注释,单纯调下接口试试。(测试方法在test包下)
    先看下单次的:


    单独调用controller的时候,bytebuddy明显快的,几乎没有损耗。
    调用web+serivce的时候时间差不多。
    下面单独调用两种情况,500次的平均值:
    仅调用Controller:    
    AOP方式: 5.7 ms,主要损耗在首次调用。

    [329, 12, 9, 6, 7, 5, 6, 5, 6, 7, 9, 8, 6, 5, 8, 8, 9, 22, 7, 11, 7, 5, 7, 6, 6, 6, 5, 6, 7, 10, 9, 9, 6, 8, 8, 13, 20, 10, 38, 7, 9, 8, 7, 10, 12, 9, 7, 7, 8, 9, 11, 11, 6, 7, 8, 5, 5, 5, 4, 5, 4, 3, 3, 4, 4, 4, 6, 4, 4, 4, 5, 6, 6, 7, 7, 6, 7, 5, 5, 8, 6, 7, 4, 7, 7, 6, 5, 5, 4, 4, 3, 4, 4, 4, 4, 5, 9, 4, 5, 5, 7, 4, 5, 11, 7, 7, 6, 9, 7, 22, 8, 14, 8, 4, 3, 4, 3, 3, 3, 4, 3, 4, 4, 5, 4, 5, 5, 11, 4, 4, 4, 4, 4, 7, 5, 8, 8, 7, 6, 6, 6, 7, 7, 4, 5, 3, 4, 4, 3, 4, 3, 4, 3, 4, 4, 5, 4, 4, 4, 4, 6, 10, 4, 6, 8, 7, 11, 12, 5, 8, 7, 6, 5, 4, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 5, 8, 6, 12, 4, 8, 5, 8, 6, 7, 6, 9, 3, 4, 6, 4, 3, 4, 3, 3, 3, 3, 3, 3, 4, 5, 5, 4, 3, 3, 3, 4, 4, 5, 4, 6, 6, 5, 4, 7, 4, 9, 4, 5, 6, 5, 8, 5, 6, 4, 4, 4, 3, 3, 4, 4, 2, 3, 3, 3, 2, 3, 3, 3, 4, 3, 4, 5, 4, 3, 3, 3, 4, 4, 5, 4, 5, 4, 7, 4, 6, 5, 5, 6, 3, 3, 4, 4, 5, 5, 5, 4, 4, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 3, 2, 2, 3, 3, 3, 3, 2, 3, 6, 4, 4, 4, 4, 4, 7, 3, 4, 6, 3, 5, 7, 5, 6, 4, 6, 7, 5, 4, 7, 6, 3, 3, 3, 4, 3, 3, 2, 3, 3, 3, 3, 2, 3, 3, 4, 4, 3, 4, 3, 4, 5, 5, 4, 10, 12, 7, 7, 5, 10, 4, 6, 6, 5, 4, 6, 6, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 4, 13, 6, 11, 4, 6, 4, 4, 6, 4, 4, 5, 4, 4, 6, 4, 3, 4, 3, 4, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 3, 2, 3, 4, 3, 4, 5, 4, 4, 6, 5, 4, 6, 4, 4, 6, 5, 4, 7, 3, 4, 4, 5, 3, 4, 4, 3, 3, 12, 5, 3, 3, 3, 4, 3, 2, 2, 2, 3, 2, 3, 3, 4, 3, 4, 4, 2, 3, 5, 4, 3, 7, 4, 4, 5, 3, 12, 21, 15, 16, 7, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 2, 2, 3, 3, 2, 2, 2, 2, 2]
    avg = OptionalDouble[5.706]
    AGENT方式: 5.4 ms,主要损耗在首次调用。
    [251, 9, 11, 12, 9, 9, 9, 9, 8, 11, 13, 6, 5, 5, 5, 6, 5, 5, 4, 6, 6, 6, 4, 10, 7, 6, 8, 7, 8, 6, 7, 7, 6, 6, 7, 6, 8, 5, 6, 5, 4, 4, 5, 5, 4, 4, 4, 4, 3, 4, 3, 5, 4, 3, 4, 4, 5, 5, 6, 5, 7, 6, 11, 10, 7, 9, 6, 5, 7, 5, 8, 6, 10, 7, 7, 7, 5, 5, 5, 5, 5, 5, 7, 5, 9, 19, 10, 7, 4, 3, 4, 4, 4, 3, 3, 4, 4, 6, 5, 4, 3, 5, 6, 4, 4, 5, 9, 10, 5, 3, 4, 5, 7, 4, 5, 10, 5, 8, 5, 11, 6, 6, 10, 4, 4, 5, 5, 7, 5, 4, 4, 7, 4, 4, 4, 5, 6, 4, 4, 5, 6, 6, 4, 6, 4, 4, 5, 8, 4, 5, 5, 4, 4, 5, 4, 4, 4, 7, 7, 10, 4, 4, 4, 3, 4, 3, 3, 4, 5, 4, 5, 8, 4, 5, 6, 7, 4, 4, 6, 5, 4, 7, 4, 4, 5, 5, 8, 5, 4, 6, 4, 9, 4, 5, 3, 3, 3, 4, 4, 3, 3, 4, 4, 4, 6, 5, 12, 6, 5, 5, 6, 8, 7, 14, 8, 5, 6, 6, 5, 5, 10, 5, 6, 5, 4, 4, 3, 4, 4, 4, 4, 5, 4, 6, 7, 4, 8, 5, 6, 4, 5, 7, 4, 6, 5, 5, 6, 3, 4, 3, 3, 4, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 4, 4, 5, 3, 5, 7, 3, 4, 5, 4, 4, 7, 4, 5, 6, 5, 8, 4, 4, 5, 4, 3, 3, 3, 3, 4, 2, 3, 6, 4, 3, 3, 3, 3, 4, 4, 3, 3, 4, 4, 5, 8, 5, 6, 5, 10, 3, 4, 14, 5, 7, 3, 7, 3, 3, 8, 3, 4, 5, 3, 4, 4, 3, 3, 4, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 6, 6, 6, 7, 5, 7, 5, 5, 4, 4, 4, 3, 5, 5, 6, 4, 6, 3, 2, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 4, 3, 3, 4, 4, 5, 8, 4, 6, 3, 5, 5, 4, 6, 8, 5, 3, 3, 4, 6, 7, 5, 8, 4, 4, 4, 5, 6, 5, 4, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 7, 3, 7, 4, 6, 6, 3, 5, 7, 4, 5, 3, 5, 5, 4, 4, 5, 3, 3, 2, 5, 3, 26, 17, 8, 20, 9, 10, 3, 3, 4, 6, 3, 5, 6, 3, 5, 5, 4, 4, 5, 4, 4, 5, 3, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 3, 2, 2, 2, 2, 3, 2, 2, 2, 3, 3, 3, 2]
    avg = OptionalDouble[5.438]

结论是在仅有cglib代理的时候(单独调用controller),耗时差不多,bytebuddy要稍快一些。
    调用Controller+Service:
    AOP方式: 5.7 ms,主要损耗在首次调用。

    [328, 14, 8, 12, 11, 9, 8, 7, 8, 8, 13, 6, 6, 6, 7, 7, 6, 6, 8, 5, 7, 8, 11, 11, 9, 8, 9, 5, 12, 8, 8, 5, 5, 8, 6, 9, 6, 8, 6, 4, 4, 5, 5, 4, 5, 7, 7, 11, 6, 9, 5, 8, 10, 5, 10, 6, 6, 6, 7, 6, 5, 4, 4, 4, 4, 3, 5, 4, 5, 5, 5, 5, 6, 7, 9, 5, 8, 6, 7, 7, 6, 4, 5, 7, 5, 8, 5, 5, 5, 4, 5, 4, 5, 4, 6, 9, 8, 9, 6, 6, 5, 4, 7, 9, 4, 4, 10, 8, 25, 30, 29, 4, 5, 6, 6, 7, 4, 6, 5, 5, 6, 6, 9, 6, 10, 12, 8, 13, 8, 6, 6, 4, 5, 4, 3, 5, 3, 3, 3, 4, 3, 3, 4, 3, 3, 3, 3, 4, 4, 4, 6, 5, 5, 6, 4, 6, 4, 4, 6, 5, 4, 5, 6, 6, 5, 5, 5, 4, 4, 4, 6, 12, 7, 5, 6, 5, 4, 5, 4, 6, 9, 8, 10, 4, 3, 6, 4, 4, 4, 4, 11, 8, 5, 4, 14, 6, 7, 5, 6, 6, 5, 5, 9, 4, 6, 8, 5, 5, 5, 6, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 2, 2, 3, 4, 4, 6, 14, 8, 6, 6, 4, 4, 9, 4, 6, 5, 6, 4, 4, 5, 6, 4, 4, 3, 4, 4, 4, 3, 5, 4, 3, 3, 5, 15, 11, 11, 6, 9, 5, 6, 5, 5, 7, 5, 8, 6, 7, 5, 4, 5, 5, 7, 4, 4, 4, 5, 5, 4, 4, 5, 9, 4, 6, 5, 4, 7, 5, 7, 6, 9, 7, 5, 7, 5, 5, 5, 5, 6, 6, 5, 6, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3, 5, 5, 8, 5, 5, 6, 8, 5, 5, 4, 4, 6, 4, 4, 5, 4, 4, 4, 3, 4, 3, 4, 4, 3, 3, 3, 3, 2, 3, 3, 3, 4, 4, 3, 7, 4, 4, 8, 4, 7, 4, 3, 8, 4, 4, 6, 5, 3, 7, 3, 4, 5, 3, 3, 2, 3, 2, 3, 3, 3, 2, 3, 3, 3, 4, 7, 4, 6, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 5, 4, 4, 4, 6, 4, 7, 4, 5, 6, 4, 4, 6, 5, 7, 4, 3, 6, 3, 3, 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 4, 3, 3, 2, 3, 4, 4, 4, 4, 4, 5, 4, 5, 3, 5, 4, 7, 4, 31, 5, 4, 5, 6, 5, 6, 5, 4, 5, 8, 4, 4, 4, 4, 4, 7, 4, 4, 4, 4, 4, 5, 4, 3, 8, 4, 32, 13, 37, 28, 5, 4, 3, 3, 3, 3, 2, 2, 3, 3, 3, 5, 6, 3, 3, 3, 4, 5, 3, 3, 3, 4]
    avg = OptionalDouble[6.186]
    AGENT方式: 5.89 ms,主要损耗在首次调用。
    [306, 16, 7, 9, 10, 11, 9, 7, 8, 11, 18, 11, 8, 9, 11, 9, 6, 6, 6, 11, 7, 8, 10, 9, 15, 9, 7, 12, 22, 8, 6, 6, 5, 5, 5, 5, 4, 4, 5, 5, 5, 4, 5, 4, 8, 7, 11, 15, 17, 8, 9, 5, 6, 8, 7, 6, 9, 5, 4, 5, 5, 4, 4, 5, 4, 5, 4, 5, 4, 4, 6, 6, 10, 6, 6, 8, 5, 8, 6, 10, 6, 9, 7, 7, 6, 8, 6, 5, 6, 5, 5, 6, 7, 7, 6, 8, 6, 10, 8, 9, 6, 4, 5, 8, 4, 5, 6, 5, 33, 19, 19, 6, 5, 4, 6, 5, 6, 5, 7, 6, 6, 7, 7, 5, 6, 6, 5, 8, 5, 4, 4, 5, 4, 3, 3, 4, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 5, 4, 4, 6, 6, 5, 7, 4, 5, 6, 4, 6, 4, 7, 6, 3, 6, 3, 3, 3, 4, 3, 4, 3, 5, 3, 4, 5, 4, 4, 3, 3, 4, 3, 8, 4, 11, 5, 6, 6, 9, 4, 5, 7, 5, 16, 6, 4, 6, 4, 4, 5, 3, 4, 2, 3, 3, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 6, 5, 6, 4, 5, 9, 5, 8, 4, 4, 5, 4, 8, 7, 8, 5, 5, 4, 5, 5, 7, 4, 6, 4, 4, 6, 4, 4, 4, 5, 4, 4, 5, 8, 18, 12, 5, 7, 5, 5, 5, 4, 4, 7, 5, 3, 3, 4, 3, 4, 3, 3, 3, 4, 3, 4, 3, 4, 3, 9, 4, 4, 4, 3, 3, 3, 5, 5, 4, 4, 5, 4, 5, 6, 4, 3, 4, 6, 4, 5, 7, 3, 5, 4, 4, 6, 4, 3, 4, 3, 3, 3, 3, 3, 2, 2, 3, 2, 3, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 7, 4, 5, 4, 4, 4, 4, 5, 4, 6, 4, 5, 7, 5, 6, 5, 3, 4, 4, 4, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 3, 3, 3, 2, 3, 4, 4, 3, 4, 2, 6, 4, 4, 5, 3, 3, 5, 4, 5, 7, 7, 5, 12, 4, 5, 4, 3, 4, 5, 5, 3, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 4, 4, 4, 6, 5, 6, 5, 5, 6, 4, 5, 6, 4, 7, 5, 5, 7, 6, 6, 4, 4, 5, 4, 5, 3, 3, 5, 4, 4, 4, 3, 4, 4, 4, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 4, 4, 5, 4, 6, 4, 4, 6, 4, 4, 7, 4, 4, 6, 2, 2, 5, 3, 4, 4, 3, 3, 18, 7, 9, 10, 21, 28, 20, 12, 5, 4, 4, 3, 3, 5, 2, 3, 3, 2, 3, 2, 2, 2, 3, 3, 3]
    avg = OptionalDouble[5.896]
    结论是在仅有cglib代理+jdk proxy的时候(调用controller+service),耗时差不多,bytebuddy要稍快一些。

事实证明,确实这样,尤其是我只是测试一个简单接口,如果链路长的时候这个差距会更加明显。

6.  结论

事实上链路追踪的框架已经很很多了,选一款适合自己的就好,如果业务个性化需求比较多,自己开发也是一个不错的选择。你也看到了,自己写一个也没有那么复杂。如果选用开源框架的话,我推荐 skywalking,社区生态整体都挺好的,而且也方便二次开发,网上文章和文档也挺多的,就不多介绍了。

推荐几篇 javaagent 的文章:
https://www.jianshu.com/p/5c62b71fd882

https://www.jianshu.com/p/b72f66da679f

https://www.jianshu.com/p/7b2072513819

全链路追踪竟然如此简单? bytebuddy搭建全链路追踪的demo 附代码相关推荐

  1. php全选删除文件,一个简单的PHP全选删除数据

    各位帮忙看看,还要修改什么!! <--------表单页面(index.php)---------> /* 链接数据库和网站配置信息 */ ?> 全选删除 function All( ...

  2. 独家 | 教你使用简单神经网络和LSTM进行时间序列预测(附代码)

    翻译:张玲 校对:丁楠雅 本文约1500字,建议阅读5分钟. 作者基于波动性标准普尔500数据集和Keras深度学习网络框架,利用python代码演示RNN和LSTM RNN的构建过程,便于你快速搭建 ...

  3. 教你搭建多变量时间序列预测模型LSTM(附代码、数据集)

    来源:机器之心 本文长度为2527字,建议阅读5分钟 本文为你介绍如何在Keras深度学习库中搭建用于多变量时间序列预测的LSTM模型. 长短期记忆循环神经网络等几乎可以完美地模拟多个输入变量的问题, ...

  4. QT5教程-搭建自己的人机交互界面(附代码)(一):QT5安装与环境配置

    一 前言 本教程目的在于记录自己开发QT项目的学习过程.适合刚刚接触QT的初学者.鉴于个人水平有限,必定错误频出,请各位前辈多多指教. 使用QT5.9.9作为开发工具,开发环境为Ubuntu20.04 ...

  5. 实例 :教你使用简单神经网络和LSTM进行时间序列预测(附代码)

    翻译:张玲  校对:丁楠雅 本文约1500字,建议阅读5分钟. 作者基于波动性标准普尔500数据集和Keras深度学习网络框架,利用python代码演示RNN和LSTM RNN的构建过程,便于你快速搭 ...

  6. SpringBoot+MyBatisPlus+ElementUI一步一步搭建前后端分离的项目(附代码下载)

    场景 一步一步教你在IEDA中快速搭建SpringBoot项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/87688277 ...

  7. 简单的个人介绍网页-主页面【附代码】

    主页面 代码1(style.css) .nav {height: 41px;border-top: 3px solid #b4fffa;border-bottom: 1px solid #edeef0 ...

  8. Vue前端环境搭建(最简单,最全)

    Vue前端环境搭建(最简单,最全) VS code下载 下载地址:https://code.visualstudio.com/ node下载 v14.15.4 版本过高不兼容部分插件,v14.15.4 ...

  9. docker环境下docker-compose一键式搭建skywalking链路追踪服务

    前言 本节内容我们使用docker-compose一键式搭建一套skywalking链路追踪服务,实现docker环境下的微服务链路追踪监控,在开始本节内容之前,我们需要提前安装好docker和doc ...

最新文章

  1. 全球最大的3D数据集公开了!标记好的10800张全景图
  2. Backbone与服务器接口之RESTful
  3. background意识(两)
  4. Go Web编程--使用bcrpyt哈希用户密码
  5. 单实例数据库迁移到rac环境(四)下
  6. 牛客练习赛22C Bitset
  7. 【LeetCode】【数组】题号:*304,二维区域和检索
  8. idea控制台搜索功能
  9. 文本聚类 java_【Java】文本聚类
  10. 数字图像处理 DCT变换
  11. Qt界面制作简单教程,调用python代码
  12. FPGA学习笔记06——数电基础知识
  13. 硬核干货 | 人脸识别的原理是什么?
  14. 文献记录(part104)--Distance-Based Outlier Detection: Consolidation and Renewed Bearing
  15. 更换一个已到使用寿命的墨盒--Epson
  16. 高中数学基础-对数2.2.2对数函数图象及其性质(上)
  17. linux fedora 10下载,Linux_Fedora 9官方最终稳定版下载地址集合,HTTP下载:http://mirror.karneval.cz/p - phpStudy...
  18. serializers.Serializer的用法
  19. Excel如何快速将图片插入到批注中?
  20. cad2006安装未找到html文件,我的CAD已安装在D驱动器上,但是在打开dwg文件时,它提示找不到C...

热门文章

  1. 前端学习(2978):上午回顾
  2. [html] android手机的微信H5弹出的软键盘挡住了文本框,如何解决?
  3. [html] html如何启动本地的exe应用?
  4. [vue] vue首页白屏是什么问题引起的?如何解决呢?
  5. [vue] vue自定义事件中父组件怎么接收子组件的多个参数?
  6. [vue-cli]vue-cli默认是单页面的,那要弄成多页面该怎么办呢
  7. 前端学习(2710):重读vue电商网站30之左侧菜单栏图标设计
  8. “约见”面试官系列之常见面试题第二十八篇之vue中的混合(minix)实例理解
  9. 前端学习(1939)vue之电商管理系统电商系统之完成全部功能
  10. 70 include指令