Skyingwalking 源码解读 oap-server 篇

Skyingwalking 源码解读 oap-server 篇

一、 OAPServerStartUp

oap-server 启动入口,调用 OAPServerBootstrap start() 方法进入主加载流程。

/**
 * OAP starter
 */
public class OAPServerStartUp {
    public static void main(String[] args) {
        // 启动主入口
        OAPServerBootstrap.start();
    }
}

二、OAPServerBootstrap

starter 的核心,加载核心配置文件,通过 ModuleManager 进行初始化。 类中只有一个 start 加载方法。

1.设置 SkyWalking 工作模式

// 获取系统属性中名为 "mode" 的字符串值并将其存储在一个名为 "mode" 的变量中。
String mode = System.getProperty("mode");
RunningMode.setMode(mode);

这行代码是在 SkyWalking 项目中的源代码,作用是获取系统属性中名为 “mode” 的字符串值并将其存储在一个名为 “mode” 的变量中。

这个系统属性可以通过在启动应用程序时使用命令行参数 “-Dmode=” 来设置,其中 “” 是你想要设置的模式的值。这个属性用来决定 SkyWalking 的工作模式,它有两个可选的值:“agent” 和 “service”。如果没有设置该属性,它将使用默认值 “service”。

在 SkyWalking 中,“agent” 模式和 “service” 模式都可以用来收集应用程序的分布式跟踪数据,但是它们的实现方式和适用场景不同。

在 “agent” 模式下,SkyWalking 代理作为一个独立的进程运行,并且与应用程序在运行时通过网络通信进行交互。代理会拦截应用程序的网络请求,将跟踪数据发送给 SkyWalking 后端,同时也会从 SkyWalking 后端接收配置信息并进行相应的处理。这种模式适用于需要对已有应用程序进行分布式跟踪的场景,可以避免对应用程序本身的修改。

在 “service” 模式下,SkyWalking 代理是应用程序的一部分,直接以代码库的形式集成到应用程序中。应用程序在运行时通过调用 SkyWalking API 的方式来记录跟踪数据,并且也可以从 SkyWalking 后端接收配置信息。这种模式适用于新应用程序的开发,或者需要更加灵活的配置和扩展的场景,因为它可以更加直接地集成到应用程序中,并且可以通过代码来进行配置和扩展。

在实际应用中,选择哪种模式取决于您的具体需求和应用程序的架构。如果您需要对已有应用程序进行跟踪,且不想修改现有代码,那么 “agent” 模式可能更为适合;如果您正在开发新的应用程序或者需要更加灵活的配置和扩展方式,那么 “service” 模式可能更为适合。

2. 配置加载器

详述请看 -> 第三章 ApplicationConfigLoader

// 进入配置加载器流程 
ApplicationConfigLoader configLoader = new ApplicationConfigLoader();
ApplicationConfiguration applicationConfiguration = configLoader.load();

3. 模块管理器初始化

详述请看 -> 第四章 ModuleManager

ModuleManager manager = new ModuleManager();
manager.init(applicationConfiguration);

三、ApplicationConfigLoader

1. application.yml

​ *处理配置文件, application.yml 作为主配置文件,并补上 application-default.yml 默认配置。 最后覆盖系统参数配置到 model 配置。*如下所示,core、storage 被称为 Module,每个 Module 都有自己的 selector ,可以选择具体的实现。 以 storage 为例,它是作为数据存储器,有多个实现,[elasticsearch 、 elasticsearch7、h2] ,selector 定义其实现为 h2 。

core:
  selector: ${SW_CORE:default}
  default:
		... 
storage:
  selector: ${SW_STORAGE:h2}
  elasticsearch:
  	...
  elasticsearch7:
  	...
  h2:
    driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
    url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1}
    user: ${SW_STORAGE_H2_USER:sa}
    metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
    maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
    numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}

2. 配置文件加载

实现 ConfigLoader接口,通过 ```T load() throws ConfigFileNotFoundException;` 方法加载并返回配置文件信息。

    @Override
    public ApplicationConfiguration load() throws ConfigFileNotFoundException {
        ApplicationConfiguration configuration = new ApplicationConfiguration();
        // 加载配置文件
        this.loadConfig(configuration);
        // 覆盖一些环境配置
        this.overrideConfigBySystemEnv(configuration);
        return configuration;
    }
2.1 loadConfig
    private void loadConfig(ApplicationConfiguration configuration) throws ConfigFileNotFoundException {
        try {
            // 源码 server-bootstrap 模块 resource 文件夹下 application.yml
            Reader applicationReader = ResourceUtils.read("application.yml");
            // 读文件,读成 map
            Map<String, Map<String, Object>> moduleConfig = yaml.loadAs(applicationReader, Map.class);
            if (CollectionUtils.isNotEmpty(moduleConfig)) {
                selectConfig(moduleConfig);
              	... 
            }
        } catch (FileNotFoundException e) {
            throw new ConfigFileNotFoundException(e.getMessage(), e);
        }
    }
    private void selectConfig(final Map<String, Map<String, Object>> moduleConfiguration) {
        Iterator<Map.Entry<String, Map<String, Object>>> moduleIterator = moduleConfiguration.entrySet().iterator();
        while (moduleIterator.hasNext()) {
 						...
            // 加载出每个 module 的 selector
            final String selector = (String) providerConfig.get(SELECTOR);
            // 加载出每个 module 的 selector 选择其实现方法
            final String resolvedSelector = PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(
                selector, System.getProperties()
            );

            // 选择出 selector 配置选择的插件,除所有非实现的配置
            providerConfig.entrySet().removeIf(e -> !resolvedSelector.equals(e.getKey()));

            if (!providerConfig.isEmpty()) {
                continue;
            }
						... 
        }
    }

四、ModuleManager

1. 模块初始化

实现 ModuleDefineHolder接口,管理了所有的 model 定义 ModuleDefine

    public void init(
        ApplicationConfiguration applicationConfiguration) throws ModuleNotFoundException, ProviderNotFoundException, ServiceNotProvidedException, CycleDependencyException, ModuleConfigException, ModuleStartException {
				
      	// 加载配置文件中的 model
        String[] moduleNames = applicationConfiguration.moduleList();
        // module 的定义,通过 SPI 机制加载 model,META-INF 下定义类会被加载
      	// 例如 skywalking/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
        ServiceLoader<ModuleDefine> moduleServiceLoader = ServiceLoader.load(ModuleDefine.class);
        ServiceLoader<ModuleProvider> moduleProviderLoader = ServiceLoader.load(ModuleProvider.class);
			
        HashSet<String> moduleSet = new HashSet<>(Arrays.asList(moduleNames));
        for (ModuleDefine module : moduleServiceLoader) {
            if (moduleSet.contains(module.name())) {
              // 模块初始化方法,详情 第五章 -> ModuleDefine
                module.prepare(this, applicationConfiguration.getModuleConfiguration(module.name()), moduleProviderLoader);
                loadedModules.put(module.name(), module);
                moduleSet.remove(module.name());
            }
        }
        // Finish prepare stage
        isInPrepareStage = false;

        // 有配置但是没插件
        if (moduleSet.size() > 0) {
            throw new ModuleNotFoundException(moduleSet.toString() + " missing.");
        }

      
        // 模块启动
        BootstrapFlow bootstrapFlow = new BootstrapFlow(loadedModules);

        bootstrapFlow.start(this);
        bootstrapFlow.notifyAfterCompleted();
    }

五、ModuleDefine

实现 ModuleProviderHolder接口,管理了所有的 model 定义 ModuleDefine

1. prepare

Run the prepare stage for the module, including finding all potential providers, and asking them to prepare. 运行模块的准备节点,找到所有的 providers,调用。

void prepare(ModuleManager moduleManager, ApplicationConfiguration.ModuleConfiguration configuration,
        ServiceLoader<ModuleProvider> moduleProviderLoader) throws ProviderNotFoundException, ServiceNotProvidedException, ModuleConfigException, ModuleStartException {
        for (ModuleProvider provider : moduleProviderLoader) {
						...
            // 运行时的类是否为 provider 内设置的类
            if (provider.module().equals(getClass())) {
                if (loadedProvider == null) {
                    loadedProvider = provider;
                    loadedProvider.setManager(moduleManager);
                    loadedProvider.setModuleDefine(this);
                }
              	...
            }
        }
  			...
            // 设置一些模块字段值, 如  GraphQLQueryConfig  的  graphql
         copyProperties(loadedProvider.createConfigBeanIfAbsent(), configuration.getProviderConfiguration(loadedProvider
                .name()), this.name(), loadedProvider.name());
  			// 完成一些模块的初始化操作
        loadedProvider.prepare();
  		...
    }

六、ModuleProvider

​ 1. 抽象类,实现 ModuleServiceHolder接口, 是 modeldefine 的实现。

​ 2. And each moduleDefine can have one or more implementation, which depends on application.yml 每个基于 application.yml 的 module 都有一个或多种实现。例如 CoreModuleProvider 中有实现。

        this.registerServiceImplementation(TopologyQueryService.class, new TopologyQueryService(getManager()));
        this.registerServiceImplementation(MetricsMetadataQueryService.class, new MetricsMetadataQueryService());
        this.registerServiceImplementation(MetricsQueryService.class, new MetricsQueryService(getManager()));
        this.registerServiceImplementation(TraceQueryService.class, new TraceQueryService(getManager()));
        this.registerServiceImplementation(BrowserLogQueryService.class, new BrowserLogQueryService(getManager()));

1. prepare

In prepare stage, the moduleDefine should initialize things which are irrelative other modules.准备加阶段,每个模块初始化步骤。

public abstract void prepare() throws ServiceNotProvidedException, ModuleStartException;
1.1 以查询模块 GraphQLQueryProvider 为例

它初始化了 graphQL 私有变量,为后续 GraphQL 做查询做使用

    @Override
    public void prepare() throws ServiceNotProvidedException, ModuleStartException {
     		// 读取 query-protocol/ 下配置文件,
        GraphQLSchema schema = SchemaParser.newParser()
                                           .file("query-protocol/common.graphqls")
                                           .resolvers(new Query(), new Mutation(), new HealthQuery(getManager()))
                                           .file("query-protocol/metadata.graphqls")
                                           .resolvers(new MetadataQuery(getManager()))
                                           .file("query-protocol/topology.graphqls")
                                           .resolvers(new TopologyQuery(getManager()))
																						... 
                                           .build()
                                           .makeExecutableSchema();
        this.graphQL = GraphQL.newGraphQL(schema).build();
    }

2.start

In start stage, the moduleDefine has been ready for interop. 启动阶段

public abstract void start() throws ServiceNotProvidedException, ModuleStartException;
2.1 以查询模块 GraphQLQueryProvider 为例

它启动了一个

    @Override
    public void start() throws ServiceNotProvidedException, ModuleStartException {
        // 通过 核心 模块, 加载了一个 jetty servlet
        JettyHandlerRegister service = getManager().find(CoreModule.NAME)
                                                   .provider()
                                                   .getService(JettyHandlerRegister.class);
        // 添加处理器,用作请求解析及数据响应
        service.addHandler(new GraphQLQueryHandler(config.getPath(), graphQL));
    }

七、 BootstrapFlow

负责启动所有 module

1. makeSequence

将所有模块分析依赖关系,加入有序列表 startupSequence

private void makeSequence() throws CycleDependencyException, ModuleNotFoundException {
        List<ModuleProvider> allProviders = new ArrayList<>();
  
 				// 遍历查询所有模块,监测其依赖模块是否存在
        for (final ModuleDefine module : loadedModules.values()) {
            String[] requiredModules = module.provider().requiredModules();
            if (requiredModules != null) {
                for (String requiredModule : requiredModules) {
                    if (!loadedModules.containsKey(requiredModule)) {
                        throw new ModuleNotFoundException(
                            requiredModule + " module is required by "
                                + module.provider().getModuleName() + "."
                                + module.provider().name() + ", but not found.");
                    }
                }
            }

            allProviders.add(module.provider());
        }

        do {
            int numOfToBeSequenced = allProviders.size();
            for (int i = 0; i < allProviders.size(); i++) {
                ModuleProvider provider = allProviders.get(i);
                String[] requiredModules = provider.requiredModules();
                // 如果有要要依赖的模块 
                if (CollectionUtils.isNotEmpty(requiredModules)) {
                  	// 标记所需模块已经启动
                    boolean isAllRequiredModuleStarted = true;
                    for (String module : requiredModules) {
                        // 先查询模块有没有在启动序列里
                        boolean exist = false;
                        for (ModuleProvider moduleProvider : startupSequence) {
                            if (moduleProvider.getModuleName().equals(module)) {
                                // 有的话标记
                                exist = true;
                                break;
                            }
                        }
                      
                     		// 如如果不存在,跳出循环
                        if (!exist) {
                            isAllRequiredModuleStarted = false;
                            break;
                        }
                    }
										
                  	// 标记模块已经启动,直接加进序列
                    if (isAllRequiredModuleStarted) {
                        startupSequence.add(provider);
                        allProviders.remove(i);
                        i--;
                    }
                } else {
                    // 没有依赖的模块直接加到启动序列
                    startupSequence.add(provider);
                    // 从列表移出,跳出加载循环
                    allProviders.remove(i);
                    i--;
                }
            }

            if (numOfToBeSequenced == allProviders.size()) {
                StringBuilder unSequencedProviders = new StringBuilder();
                allProviders.forEach(provider -> unSequencedProviders.append(provider.getModuleName())
                                                                     .append("[provider=")
                                                                     .append(provider.getClass().getName())
                                                                     .append("]\n"));
                throw new CycleDependencyException(
                    "Exist cycle module dependencies in \n" + unSequencedProviders.substring(0, unSequencedProviders
                        .length() - 1));
            }
        }
        while (allProviders.size() != 0);
    }

2.start

负责模块启动

    void start(
        ModuleManager moduleManager) throws ModuleNotFoundException, ServiceNotProvidedException, ModuleStartException {
        for (ModuleProvider provider : startupSequence) {
            LOGGER.info("start the provider {} in {} module.", provider.name(), provider.getModuleName());
            // 检查依赖
            provider.requiredCheck(provider.getModule().services());
						
            // 调用启动方法 详情见第六章 -> ModuleProvider 
            provider.start();
        }
    }

​ 先分析主要流程,后续更新详细源码…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值