SkyWalking之agent

SkyWalking 的 agent 使用了一种称为字节码增强(bytecode instrumentation)的技术来实现代码增强、日志输出以及调用链路的获取。这种技术可以在程序运行时动态地修改类的字节码,插入特定的逻辑,例如记录方法的调用、参数和返回值等。

字节码增强技术

SkyWalking 主要利用了以下几种字节码增强技术:

  1. Java Agent
  2. Byte Buddy
  3. ASM
1. Java Agent

Java Agent 是一种允许在 JVM 启动时或运行时动态加载和修改字节码的机制。SkyWalking 使用 Java Agent 来插入其自身的字节码增强逻辑。

  • Premain 和 Agentmain 方法 :Java Agent 使用 premain 方法在 JVM 启动时执行,或者使用 agentmain 方法在 JVM 运行时动态加载。
java 复制代码
import java.lang.instrument.Instrumentation;

public class MyAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("Agent is running");
        // 可以在这里添加字节码增强逻辑
    }

    public static void agentmain(String agentArgs, Instrumentation inst) {
        System.out.println("Agent is dynamically loaded");
        // 可以在这里添加字节码增强逻辑
    }
}
2. Byte Buddy

Byte Buddy 是一个强大的字节码操作库,SkyWalking 使用 Byte Buddy 来简化字节码操作。Byte Buddy 提供了高级的 API 来生成、修改和操作字节码。

  • 示例:通过 Byte Buddy 创建一个代理类,插入方法拦截逻辑。
java 复制代码
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.instrument.Instrumentation;

public class MyAgent {
    public static void premain(String agentArgs, Instrumentation inst) {
        new AgentBuilder.Default()
            .type(ElementMatchers.nameContains("MyService"))
            .transform((builder, typeDescription, classLoader, javaModule) ->
                builder.visit(Advice.to(MyServiceAdvice.class).on(ElementMatchers.any()))
            ).installOn(inst);
    }
}

class MyServiceAdvice {
    @Advice.OnMethodEnter
    static void onEnter() {
        System.out.println("Before method execution");
    }

    @Advice.OnMethodExit
    static void onExit() {
        System.out.println("After method execution");
    }
}
3. ASM

ASM 是一个低级的字节码操作库,可以直接操作 JVM 字节码。SkyWalking 使用 ASM 来实现更细粒度的字节码操作。

  • 示例:使用 ASM 来修改字节码,在方法调用前后插入日志。
java 复制代码
import org.objectweb.asm.*;

public class MyClassVisitor extends ClassVisitor {
    public MyClassVisitor(ClassVisitor cv) {
        super(Opcodes.ASM9, cv);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        return new MyMethodVisitor(mv);
    }

    class MyMethodVisitor extends MethodVisitor {
        public MyMethodVisitor(MethodVisitor mv) {
            super(Opcodes.ASM9, mv);
        }

        @Override
        public void visitCode() {
            super.visitCode();
            mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
            mv.visitLdcInsn("Before method execution");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
        }

        @Override
        public void visitInsn(int opcode) {
            if (opcode == Opcodes.RETURN) {
                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
                mv.visitLdcInsn("After method execution");
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
            }
            super.visitInsn(opcode);
        }
    }
}

调用链路的获取

通过上述字节码增强技术,SkyWalking 在每个需要监控的方法前后插入代码,以捕获方法调用、参数、返回值和异常等信息。这些信息被用来生成分布式调用链路(Trace),并将其发送到 SkyWalking 的后端进行存储和分析。

  1. 进入方法时:记录当前时间戳、方法名、类名、参数等信息,并生成一个 Trace Segment。
  2. 方法执行完毕后:记录结束时间戳、返回值或异常信息,完成一个 Trace Segment。
  3. 分布式追踪:通过唯一的 Trace ID 和 Segment ID 将多个 Trace Segment 关联起来,形成完整的调用链路。

这些技术和方法结合使用,使得 SkyWalking 能够高效地收集和分析分布式系统的性能数据,并提供可视化的调用链路分析工具。

相关推荐
xiaohe0711 小时前
SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪
spring boot·后端·skywalking
代码的奴隶(艾伦·耶格尔)1 天前
SkyWalking链路追踪安装和使用
skywalking
Darkdreams4 天前
分布式监控Skywalking安装及使用教程(保姆级教程)
分布式·skywalking
zhglhy9 天前
Apache SkyWalking分布式链路实现
分布式·apache·skywalking
飞火流星020271 个月前
SkyWalking异步日志采集数据压缩从头到尾实现及踩坑笔记
skywalking·skywalking日志采集·skywalking日志压缩·macos上验证sw日志压缩·sw异步采集日志实现数据压缩
叱咤少帅(少帅)1 个月前
Skywalking v10.x 部署
skywalking
EQylwUYz1 个月前
基于DDPG算法优化四旋翼飞行器PD控制:从理论到Matlab实现
skywalking
dfyx9991 个月前
SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪
spring boot·后端·skywalking
_运维那些事儿2 个月前
skywalking链路追踪
java·运维·ci/cd·软件构建·skywalking·devops
虫小宝2 个月前
淘客返利系统的日志追踪与链路监控:SkyWalking 与 OpenTelemetry 集成方案
c#·linq·skywalking