【Skywalking】Java agent如何启动后台任务

537 阅读2分钟

前言

Java Agent包含一些后台任务,例如

  • 采集JVM参数
  • 将span发送到OAP服务器
  • 等等

本身Java-Agent是一个自动化埋点的探针程序,它是如何启动自己的后台任务的呢?

如何启动后台任务

首先Java-Agent项目作为一个自动埋点的项目,程序的入口肯定是Instrumentation机制的permain方法:

因此从permain方法入手:查看permain方法的实现,除了修改class实现外,还可以观察到:

1643010641381.png

很明显,这就是启动后台服务的语句。其中ServiceManager是一个枚举类,接着我们直接查看boot函数的实现:

public enum ServiceManager {
    // 省略一些代码...
    private Map<Class, BootService> bootedServices = Collections.emptyMap();
​
    public void boot() {
        bootedServices = loadAllServices();
​
        prepare();
        startup();
        onComplete();
    }
    
}
​
public interface BootService {
    void prepare() throws Throwable;
​
    void boot() throws Throwable;
​
    void onComplete() throws Throwable;
​
    void shutdown() throws Throwable;
​
    default int priority() {
        return 0;
    }
}

boot函数首先加载所有的服务到私有属性bootedServices中。然后调用prepare做前置操作,然后启动所有服务,最后调用完毕勾子。而BootService是一个接口,明显采用模板的设计模式。

接着具体看看loadAllServices函数的实现:

 private Map<Class, BootService> loadAllServices() {
        Map<Class, BootService> bootedServices = new LinkedHashMap<>();
        List<BootService> allServices = new LinkedList<>();
        load(allServices);
        for (final BootService bootService : allServices) {
        // 省略一些过滤处理...
        }
        return bootedServices;
    }
​
​
void load(List<BootService> allServices) {
        // 使用Java的SPI机制,加载所有的BootService实现
        for (final BootService bootService : ServiceLoader.load(BootService.class, AgentClassLoader.getDefault())) {
            allServices.add(bootService);
      }
    }

可以看到load函数中使用ServiceLoader来加载所有实现BootService接口的类,那说明这是采用SPI机制加载进来的。那么我们查看meta-info的services目录

1643011294561.png

该文件列出了一共19个BootService的实现类名,其内容如下:

// 发送Trace信息给OAP服务器的后台任务
org.apache.skywalking.apm.agent.core.remote.TraceSegmentServiceClient
// 实现采样的后台任务
org.apache.skywalking.apm.agent.core.sampling.SamplingService
org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager
// 实现发送JVM状态的后台任务    
org.apache.skywalking.apm.agent.core.jvm.JVMMetricsSender
// 实现采集JVM状态的后台任务
org.apache.skywalking.apm.agent.core.jvm.JVMService
org.apache.skywalking.apm.agent.core.remote.ServiceManagementClient
...

总结

1、所有的后台任务都实现了org.apache.skywalking.apm.agent.core.boot.BootService接口,并实现了

  • prepare
  • boot
  • onComplete
  • shutdown

四个模板方法,方便服务管理层进行调用和统一管理。

2、另外在permain函数中通过SPI加载所有BootService实现类(均在meta-info中列清单中),然后调用前三个模板方法,启动后台任务。

查找源码的思路

分享下查看源码思路:观察配置文件,有这个参数:(猜测该参数为将Span发送给OAP服务器这类任务所用)

1643010295263.png

所以在源码中查找这个参数,然后参数的使用地方,发现是一个BootService,那么顺藤摸瓜就可以找到整个后台任务启动的机制了。

\