skywalking 源码

可以看手写skywalking查找插件的代码
https://www.bilibili.com/video/BV1Jv4y1a7Kw?p=20&vd_source=d9a52d82a1f11ceeeb7021c93269e8d2

源码核心是SkyWalkingAgent

找到一堆插件,来对符合条件的类来代理
在这里插入图片描述
通过AbstractClassEnhancePluginDefine.define方法来。
如果有很多版本的插件,spring有2.0版本,3.0版本,4.0版。
具体使用哪个版本,看被增加的类使用的是哪个版本的spring
比如

  • spring 2有(A类,B类,C类)
  • spring3 有(B类,C类,D类)
  • spring4有 (B类,C类,D类)

如果应用程序使用的spring2,那么一定会有A类,那skywalking会选择spring2插件匹配,如果应用程序使用的spring4,由于spring3和spring4的类都相同,那么在比较spring3和spring4中的方法。
找出各种独有的方法来匹配,然后在确定使用哪个版本的插件
在这里插入图片描述
以拦截实例方法为例ClassEnhancePluginDefine.enhanceInstance

在这里插入图片描述
拦截到的方法,会交给InstMethodsInter来处理。像aop一样。

在这里插入图片描述

package com.test;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class IndexController {

    
    @RequestMapping("/hello")
    public Object test(){
        return "hello";
    }

}

通过arthas 反编译的代码

       package com.test;

       import com.test.IndexController;
       import java.lang.reflect.Method;
       import java.util.concurrent.Callable;
       import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ConstructorInter;
       import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
       import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter;
       import org.springframework.web.bind.annotation.RequestMapping;
       import org.springframework.web.bind.annotation.RestController;

       @RestController
       public class IndexController
       implements EnhancedInstance {
           private volatile Object _$EnhancedClassField_ws;
           public static volatile /* synthetic */ InstMethodsInter delegate$frmhjm0;
           public static volatile /* synthetic */ InstMethodsInter delegate$iuour40;
           public static volatile /* synthetic */ ConstructorInter delegate$50sob50;
           private static final /* synthetic */ Method cachedValue$L2xuREhn$gvchht3;
           public static volatile /* synthetic */ InstMethodsInter delegate$acsh691;
           public static volatile /* synthetic */ InstMethodsInter delegate$qc4vlq1;
           public static volatile /* synthetic */ ConstructorInter delegate$vm2r3i1;
           private static final /* synthetic */ Method cachedValue$ImSA9xmx$gvchht3;

           public IndexController() {
               this(null);
               delegate$vm2r3i1.intercept(this, new Object[0]);
           }

           private /* synthetic */ IndexController(auxiliary.74kq0FAk kq0FAk) {
           }

           @RequestMapping(value={"/hello"})
           public Object test() {
               return delegate$qc4vlq1.intercept(this, new Object[0], (Callable<?>)new auxiliary.0hTUYoEs(this), cachedValue$ImSA9xmx$gvchht3);
           }

           private /* synthetic */ Object test$original$bo9sTfYx() {
/*15*/         return "hello";
           }

           static {
               ClassLoader.getSystemClassLoader().loadClass("org.apache.skywalking.apm.dependencies.net.bytebuddy.dynamic.Nexus").getMethod("initialize", Class.class, Integer.TYPE).invoke(null, IndexController.class, 1905055592);
               cachedValue$ImSA9xmx$gvchht3 = IndexController.class.getMethod("test", new Class[0]);
           }

           final /* synthetic */ Object test$original$bo9sTfYx$accessor$ImSA9xmx() {
               return this.test$original$bo9sTfYx();
           }
       }

有上面的源码可以看出,对test方法进行了增强,内部其实是调用了delegate$qc4vlq1的intercept方法,就是InstMethodsInter中aop相关逻辑
会执行InstanceMethodsAroundInterceptor接口的3个方法。

比如上面IndexController这个类,因为有@RestController 注解,所以就被对应的RestControllerInstrumentation给匹配上了

在这里插入图片描述

在这里插入图片描述
增强后的代码会交个org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.RequestMappingMethodInterceptor来处理
在这里插入图片描述
可以看到,当我们调用http://localhost:8088/hello 这个接口时,就被拦截到了,然后调用RequestMappingMethodInterceptor的beforeMethod方法进行处理
在这里插入图片描述

以duboo插件为类DubboInterceptor的拦截器实现了InstanceMethodsAroundInterceptor
在这里插入图片描述

SPAN

在这里插入图片描述

span 记录

1.EntrySpan

springboot项目 当一个请求到达ctroller之前,会先tomcat==>spring mvc 然后在到达业务

在这里插入图片描述

1.在到达tomcat的时候,会先创建一个EntrySpan。同时记录下Tags和SpanLayer的信息。
org.apache.skywalking.apm.plugin.tomcat78x.TomcatInvokeInterceptor

在这里插入图片描述
peek 这个方法其实是一个类似栈的数据结构activeSpanStack,先判断下activeSpanStack有没有数据,没有数据的说明,tomcat是一个入口,创建了EntrySpan后,放到activeSpanStack中
在这里插入图片描述

2.进入到springMVC后,因为不知道有没有创建EntrySpan ,所以又进行了创建
org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.AbstractMethodInterceptor#beforeMethod

在这里插入图片描述
由于tomcat已经创建了entrySpan,所以没有创建新的,同时spring MVC的layer,tags和logs会覆盖tomcat设置的值,
也就是说EntrySpan记录的信息最靠近服务提供测的信息
在这里插入图片描述

ExitSpan 和LocalSpan

在这里插入图片描述

请求进来是从tomcat------>spring mvc—>getUser ,EntrySpan是tomcat创建,springmvc来复用
请求返回是 从getUser—>spring mvc---->tomcat 这个时候是插件嵌套,springMVC创建ExitSpan,tomcat来复用
比如上图中getUser方法,需要调用redis和Mysql,这个时候就不在同一个服务或者线程了,需要创建二个ExitSpan

LocalSpan 可以用来记录本地的一些方法,比如上图的getUser----->checkUser

(1) tomcat 创建EntrySpan

在这里插入图片描述
(2)spring mvc复用EntrySpan

在这里插入图片描述
(3)org.apache.skywalking.apm.plugin.lettuce.v5.AsyncCommandMethodInterceptor#beforeMethod
创建LocalSpan
写了本地的方法好像没有创建LocalSpan
在这里插入图片描述

(4) redis 创建ExitSpan
org.apache.skywalking.apm.plugin.lettuce.v5.RedisChannelWriterInterceptor#beforeMethod
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值