• skywalking源码--agent配置加载


    本源码来自于skywalking-agent 8.9.0版本
    本节主要讲解skywalking-agent的配置文件加载流程,该实现在 apm-sniffer模块的apm-agent-core 模块里面。但是入口依然是在 apm-agent 模块的 SkyWalkingAgent 的premain方法里面。

    注:本篇文章主要是作为自己看书后的总结,内容有可能会存在一些个人理解上的偏差,如果有网友找出问题欢迎提出,感谢!!!如果我理解上的错误误导了您,在此表示抱歉!!!

    相关源码

    org.apache.skywalking.apm.agent.SkyWalkingAgent 类

    
    try {
                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);
            }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这里 SnifferConfigInitializer.initializeCoreConfig(agentArgs) 就是加载配置的入口。

    疑问

    这里来个小问题,为什么加载配置的时候再catch的里面打印日志时需要通过 LogManager.getLogger 重新获取日志类型,而不是直接打印日志?这个等文章结尾再讲解

    org.apache.skywalking.apm.agent.core.conf.SnifferConfigInitializer 类

    public static void initializeCoreConfig(String agentOptions) {
            AGENT_SETTINGS = new Properties();
            try (final InputStreamReader configFileStream = loadConfig()) {
                AGENT_SETTINGS.load(configFileStream);
                for (String key : AGENT_SETTINGS.stringPropertyNames()) {
                    String value = (String) AGENT_SETTINGS.get(key);
                    AGENT_SETTINGS.put(key, PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(value, AGENT_SETTINGS));
                }
    
            } catch (Exception e) {
                LOGGER.error(e, "Failed to read the config file, skywalking is going to run in default config.");
            }
    
            try {
                overrideConfigBySystemProp();
            } catch (Exception e) {
                LOGGER.error(e, "Failed to read the system properties.");
            }
    
            agentOptions = StringUtil.trim(agentOptions, ',');
            if (!StringUtil.isEmpty(agentOptions)) {
                try {
                    agentOptions = agentOptions.trim();
                    LOGGER.info("Agent options is {}.", agentOptions);
    
                    overrideConfigByAgentOptions(agentOptions);
                } catch (Exception e) {
                    LOGGER.error(e, "Failed to parse the agent options, val is {}.", agentOptions);
                }
            }
    
            initializeConfig(Config.class);
            // reconfigure logger after config initialization
            configureLogger();
            LOGGER = LogManager.getLogger(SnifferConfigInitializer.class);
    
            if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {
                throw new ExceptionInInitializerError("`agent.service_name` is missing.");
            } else {
                if (StringUtil.isNotEmpty(Config.Agent.NAMESPACE) || StringUtil.isNotEmpty(Config.Agent.CLUSTER)) {
                    Config.Agent.SERVICE_NAME = StringUtil.join(
                        SERVICE_NAME_PART_CONNECTOR,
                        Config.Agent.SERVICE_NAME,
                        Config.Agent.NAMESPACE,
                        Config.Agent.CLUSTER
                    );
                }
            }
            if (StringUtil.isEmpty(Config.Collector.BACKEND_SERVICE)) {
                throw new ExceptionInInitializerError("`collector.backend_service` is missing.");
            }
            if (Config.Plugin.PEER_MAX_LENGTH <= 3) {
                LOGGER.warn(
                    "PEER_MAX_LENGTH configuration:{} error, the default value of 200 will be used.",
                    Config.Plugin.PEER_MAX_LENGTH
                );
                Config.Plugin.PEER_MAX_LENGTH = 200;
            }
    
            IS_INIT_COMPLETED = true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    主要流程

    1、加载配置文件
    2、通过系统变量重新设置相关配置
    3、通过启动参数重新设置相关配置
    4、初始化配置
    5、重新设置日志类型
    6、做一些配置信息的检查及容错

    加载配置文件
    private static InputStreamReader loadConfig() throws AgentPackageNotFoundException, ConfigNotFoundException {
    // 获取是否存在 SPECIFIED_CONFIG_PATH 系统变量,这个变量用于设置配置文件路径,
    // 如果存在查看这个变量的值是否为空,非空加载该路径下的文件;空的话加载默认路径(/config/agent.config)下的文件
    // 所以可能存在有些场景下需要将配置文件放在指定位置,那么可以通过这种方式设置
            String specifiedConfigPath = System.getProperty(SPECIFIED_CONFIG_PATH);
            File configFile = StringUtil.isEmpty(specifiedConfigPath) ? new File(
                AgentPackagePath.getPath(), DEFAULT_CONFIG_FILE_NAME) : new File(specifiedConfigPath);
    // 如果存在这个路径,且是该路径下的是文件,那么读取该文件
            if (configFile.exists() && configFile.isFile()) {
                try {
                    LOGGER.info("Config file found in {}.", configFile);
    
                    return new InputStreamReader(new FileInputStream(configFile), StandardCharsets.UTF_8);
                } catch (FileNotFoundException e) {
                    throw new ConfigNotFoundException("Failed to load agent.config", e);
                }
            }
            throw new ConfigNotFoundException("Failed to load agent.config.");
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    其中 AgentPackagePath.getPath() 的作用是用于定位出 skywalking-agent.jar包的路径,因为知道了它的路径,那么其他的一些包的路径也就知道了,因为在默认情况下打包后的目录结构是固定的。

    通过系统变量重新设置相关配置
    
    private static void overrideConfigBySystemProp() {
            Properties systemProperties = System.getProperties();
            for (final Map.Entry<Object, Object> prop : systemProperties.entrySet()) {
                String key = prop.getKey().toString();
                if (key.startsWith(ENV_KEY_PREFIX)) {
                    String realKey = key.substring(ENV_KEY_PREFIX.length());
                    AGENT_SETTINGS.put(realKey, prop.getValue());
                }
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    如果系统中设置了相关的gaent配置,那么就进行替换。

    初始化配置
    
    public static void initializeConfig(Class configClass) {
            if (AGENT_SETTINGS == null) {
                LOGGER.error("Plugin configs have to be initialized after core config initialization.");
                return;
            }
            try {
            // 将 Properties 内的值赋值给 Config ,这里 Config 内的属性是以模块+配置的形式设计的,同样 配置文件中也是以模块+配置的形式设计的,不同的是配置文件内的属性都是小写的。只要将大小写相互转化就可以找到相互的映射关系
                ConfigInitializer.initialize(AGENT_SETTINGS, configClass);
            } catch (IllegalAccessException e) {
                LOGGER.error(e,
                             "Failed to set the agent settings {}"
                                 + " to Config={} ",
                             AGENT_SETTINGS, configClass
                );
            }
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    重新设置日志类型
    static void configureLogger() {
            switch (Config.Logging.RESOLVER) {
                case JSON:
                    LogManager.setLogResolver(new JsonLogResolver());
                    break;
                case PATTERN:
                default:
                    LogManager.setLogResolver(new PatternLogResolver());
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这里会根据配置中设置的日志格式进行设置

    配置信息的检查及容错
    // 服务名是必须的,因为这涉及到服务注册
    if (StringUtil.isEmpty(Config.Agent.SERVICE_NAME)) {
                throw new ExceptionInInitializerError("`agent.service_name` is missing.");
            } else {
            // 命名空间也是必须的,这也涉及到服务注册
                if (StringUtil.isNotEmpty(Config.Agent.NAMESPACE) || StringUtil.isNotEmpty(Config.Agent.CLUSTER)) {
                    Config.Agent.SERVICE_NAME = StringUtil.join(
                        SERVICE_NAME_PART_CONNECTOR,
                        Config.Agent.SERVICE_NAME,
                        Config.Agent.NAMESPACE,
                        Config.Agent.CLUSTER
                    );
                }
            }
            // 后端地址也是必须的,这涉及到服务注册和心跳,因为数据上报可以通过kafka,所以数据上报可以不受他的影响
            if (StringUtil.isEmpty(Config.Collector.BACKEND_SERVICE)) {
                throw new ExceptionInInitializerError("`collector.backend_service` is missing.");
            }
            // 因为peer地址一般都大于3,所以如果设置的太小会强制改为200
            if (Config.Plugin.PEER_MAX_LENGTH <= 3) {
                LOGGER.warn(
                    "PEER_MAX_LENGTH configuration:{} error, the default value of 200 will be used.",
                    Config.Plugin.PEER_MAX_LENGTH
                );
                Config.Plugin.PEER_MAX_LENGTH = 200;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    解答

    大家应该看到了,在加载配置的代码里面加载完配置后会重新设置日志类型,这个时候新的日志类型可能和原先刚开始的日志类型不一致,所以需要在最外面重新获取一次日志类型,不然日志类型还是原先skywalking默认的日志类型。

  • 相关阅读:
    threejs的dat.gui辅助工具的使用
    Java秒杀系统方案优化
    Kaldi安装(Linux环境)
    nginx
    Go语言用Resty库编写的音频爬虫代码
    mingw 编译 curl ,Qt 工程使用
    便捷建筑工程行业招采管理,供应商协同平台精准匹配企业需求,撮合交易
    基于onbar的备份与恢复实验
    Linux启动过程详解
    用DolphinScheduler轻松实现Flume数据采集任务自动化!
  • 原文地址:https://blog.csdn.net/SO_zxn/article/details/127722609