Skywalking流程分析_1(主要流程分析)

前言

skywalking作为目前最常用的APM监控,其重要性不可言喻,本人也是针对公司业务做了很多定制化的改造,其内部的原理设计很是巧妙,尤其是自定义agentClassLoader类加载的部分更是值得去借鉴这种思想。本系列将skywalking内部原理进行剖析,让大家更加容易体会启动的精髓

版本

  • 8.14.0

特点

  • 使用javaagent静态启动的方式
  • 使用bytebuddy的框架,入口是permain()方法
  • 在类加载时可以对字节码进行随意的修改,只要符合规范即可
  • 将插件自定义了类加载器进行了完美的隔离

入口

apm-sniffer/apm-agent模块下,pom的配置

xml 复制代码
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <premain.class>org.apache.skywalking.apm.agent.SkyWalkingAgent</premain.class>
    <!-- 省略... -->
</properties>
<plugin>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <createDependencyReducedPom>true</createDependencyReducedPom>
                <createSourcesJar>true</createSourcesJar>
                <shadeSourcesContent>true</shadeSourcesContent>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <manifestEntries>
                            <Premain-Class>${premain.class}</Premain-Class>
                            <Can-Redefine-Classes>${can.redefine.classes}</Can-Redefine-Classes>
                            <Can-Retransform-Classes>${can.retransform.classes}</Can-Retransform-Classes>
                        </manifestEntries>
                    </transformer>
                </transformers>
                <!-- 省略... -->
            </configuration>
        </execution>
    </executions>
</plugin>

在这里指定了org.apache.skywalking.apm.agent.SkyWalkingAgent的入口,下面就是重要的premain方法

SkyWalkingAgent.premain

java 复制代码
public class SkyWalkingAgent {
private static ILog LOGGER = LogManager.getLogger(SkyWalkingAgent.class);

/**
 * Main entrance. Use byte-buddy transform to enhance all classes, which define in plugins.
 */
public static void premain(String agentArgs, Instrumentation instrumentation) throws PluginException {
    final PluginFinder pluginFinder;
    try {
        //读取配置文件和核心jar
        SnifferConfigInitializer.initializeCoreConfig(agentArgs);
    } catch (Exception e) {
        // try to resolve a new logger, and use the new logger to write the error log here
        LogManager.getLogger(SkyWalkingAgent.class)
                  .error(e, "SkyWalking agent initialized failure. Shutting down.");
        return;
    } finally {
        // refresh logger again after initialization finishes
        LOGGER = LogManager.getLogger(SkyWalkingAgent.class);
    }

    if (!Config.Agent.ENABLE) {
        LOGGER.warn("SkyWalking agent is disabled.");
        return;
    }

    try {
        //读取插件和加载插件
        pluginFinder = new PluginFinder(new PluginBootstrap().loadPlugins());
    } catch (AgentPackageNotFoundException ape) {
        LOGGER.error(ape, "Locate agent.jar failure. Shutting down.");
        return;
    } catch (Exception e) {
        LOGGER.error(e, "SkyWalking agent initialized failure. Shutting down.");
        return;
    }
    //创建byteBuddy
    final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));

    //哪些类进行忽略
    AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
        nameStartsWith("net.bytebuddy.")
            .or(nameStartsWith("org.slf4j."))
            .or(nameStartsWith("org.groovy."))
            .or(nameContains("javassist"))
            .or(nameContains(".asm."))
            .or(nameContains(".reflectasm."))
            .or(nameStartsWith("sun.reflect"))
            .or(allSkyWalkingAgentExcludeToolkit())
            .or(ElementMatchers.isSynthetic()));

    JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();
    try {
        /*
        * 里面有个重点逻辑 把一些类注入到Boostrap类加载器中 为了解决Bootstrap类加载器不能访问App类加载器中的内容的问题
        * */
        agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);
    } catch (Exception e) {
        LOGGER.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down.");
        return;
    }
    /**
     * 绕开jdk模块化问题
     * */
    try {
        agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);
    } catch (Exception e) {
        LOGGER.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down.");
        return;
    }
    //根据配置是否将修改后的字节码保存到磁盘/内存
    if (Config.Agent.IS_CACHE_ENHANCED_CLASS) {
        try {
            agentBuilder = agentBuilder.with(new CacheableTransformerDecorator(Config.Agent.CLASS_CACHE_MODE));
            LOGGER.info("SkyWalking agent class cache [{}] activated.", Config.Agent.CLASS_CACHE_MODE);
        } catch (Exception e) {
            LOGGER.error(e, "SkyWalking agent can't active class cache.");
        }
    }

    agentBuilder.type(pluginFinder.buildMatch())//指定byteBuddy要拦截的类
                .transform(new Transformer(pluginFinder))//指定字节码增强的工具
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)//redefine和retransformation的区别在于是否保留修改前的内容
                .with(new RedefinitionListener())
                .with(new Listener())
                .installOn(instrumentation);//将agent安装到instrumentation

    PluginFinder.pluginInitCompleted();

    try {
        //启动服务
        //将BootService的这些服务依次进行启动
        ServiceManager.INSTANCE.boot();
    } catch (Exception e) {
        LOGGER.error(e, "Skywalking agent boot failure.");
    }
    //将BootService的这些服务依次进行关闭
    Runtime.getRuntime()
           .addShutdownHook(new Thread(ServiceManager.INSTANCE::shutdown, "skywalking service shutdown thread"));
}

premain的大致流程为

  • 读取配置文件
  • 加载插件
  • 创建byteBuddy
  • 做一些额外的准备工作
  • 启动服务
  • 关闭服务钩子

在以后得系列中我们会来逐步分析每个阶段的流程

相关推荐
XT46251 天前
skywalking 原理
skywalking
yangmf20402 天前
APM 系列(一):Skywalking 与 Easyearch 集成
大数据·elasticsearch·搜索引擎·skywalking
sniper_fandc5 天前
Spring Cloud系列—SkyWalking告警和飞书接入
spring cloud·skywalking
飞火流星020271 个月前
SkyWalking异步采集spring gateway日志
gateway·skywalking·日志监控·gateway链路监控
鼠鼠我捏,要死了捏1 个月前
基于SkyWalking的微服务APM监控实战指南
skywalking·apm·microservices
HeXDev2 个月前
【SkyWalking】服务端部署与微服务无侵入接入实战指南
java·微服务·架构·skywalking·链路追踪·微服务治理
HeXDev2 个月前
【SkyWalking】配置告警规则并通过 Webhook 推送钉钉通知
skywalking·链路追踪·微服务监控
老三牛擦2 个月前
熟悉Docker及Docker-Compose。熟悉Linux常用命令,编写基本Shell脚本。可搭建Jenkins进行Dev/Ops。
skywalking
老三牛擦2 个月前
熟练掌握RabbitMQ和Kafka的使用及相关应用场景。异步通知与解耦,流量削峰,配合本地消息表实现事务的最终一致性并解决消息可靠、顺序消费和错误重试等问题
skywalking
老三牛擦2 个月前
熟悉多线程与并发编程,理解各类锁机制,熟悉JUC并发多线程及线程池,熟练异步编排编码,熟悉Redisson在分布式场景下各类锁的应用场景和并发控制原理。
skywalking