- 可观测性
- 后端
- 微服务
- 云原生
【免费下载链接】skywalking
APM, Application Performance Monitoring System
SkyWalking OAP 的大部分配置通过application.yml与操作系统环境变量下发,而其中的部分配置支持由上游管理系统动态下发。本文聚焦于其中基于Nacos 2.x的动态配置中心(Dynamic Configuration Center,DCC)实现:从application.yml的启用配置、Nacos 中的存储模型(Single / Group 两种配置形态),到configuration-nacos模块的源码级同步与监听原理,并给出集成测试验证方式。读完本文,你将掌握如何把 OAP 的agent-analyzer.default.slowDBAccessThreshold、core.default.endpoint-name-grouping-openapi等配置项迁入 Nacos,实现不停机热更新。
一、动态配置机制与 Nacos 接入前提
SkyWalking 的配置体系以 application.yml 和系统环境变量为主,同时支持「Single(单值)」与「Group(组)」两种动态配置形态(详见 动态配置总览)。由于该能力依赖上游配置中心服务,因此默认处于关闭状态(selector默认指向none),需要显式启用。
Nacos 2.x 是 SkyWalking 支持的 DCC 实现之一(其余还包括 Zookeeper、Etcd、Consul、Apollo、Kubernetes Configmap、gRPC DCS 等,见 dynamic-config.md 中的实现清单)。接入 Nacos 后,OAP 会在后台周期性拉取并监听 Nacos 上的配置变更,将变化实时同步到内存中的配置注册表,从而驱动采样阈值、告警规则、端点分组规则等配置的动态调整。
二、在 application.yml 中启用 Nacos 动态配置
在 OAP 的application.yml(即 oap-server/server-starter/src/main/resources/application.yml)中,将configuration.selector切换为nacos,并填写 Nacos 服务端连接参数:
configuration: selector: ${SW_CONFIGURATION:nacos} nacos: # Nacos Server Host serverAddr: ${SW_CONFIG_NACOS_SERVER_ADDR:127.0.0.1} # Nacos Server Port port: ${SW_CONFIG_NACOS_SERVER_PORT:8848} # Nacos Configuration Group group: ${SW_CONFIG_NACOS_SERVER_GROUP:skywalking} # Nacos Configuration namespace namespace: ${SW_CONFIG_NACOS_SERVER_NAMESPACE:} # Unit seconds, sync period. Default fetch every 60 seconds. period: ${SW_CONFIG_NACOS_PERIOD:60} # the name of current cluster, set the name if you want to upstream system known. clusterName: ${SW_CONFIG_NACOS_CLUSTER_NAME:default}其中selector: ${SW_CONFIGURATION:nacos}表示可通过环境变量SW_CONFIGURATION覆盖默认值(默认nacos),例如在容器/编排环境中设置SW_CONFIGURATION=nacos即可切换。各参数含义与默认值如下:
| 参数 | 环境变量覆盖 | 默认值 | 说明 |
|---|---|---|---|
serverAddr | SW_CONFIG_NACOS_SERVER_ADDR | 127.0.0.1 | Nacos Server 主机地址 |
port | SW_CONFIG_NACOS_SERVER_PORT | 8848 | Nacos Server 端口 |
group | SW_CONFIG_NACOS_SERVER_GROUP | skywalking | 配置所属 Group,OAP 读写配置时统一使用该 Group |
namespace | SW_CONFIG_NACOS_SERVER_NAMESPACE | 空 | 配置所属 Namespace;留空时使用 Nacos 默认(public)命名空间 |
period | SW_CONFIG_NACOS_PERIOD | 60 | 周期同步间隔,单位秒,默认每 60 秒全量拉取一次 |
clusterName | SW_CONFIG_NACOS_CLUSTER_NAME | default | 当前集群名称(原文档列出,供上游系统识别) |
需要特别说明的是,原文档(dynamic-config-nacos.md)中仅列出上述 6 项;而当前仓库源码中的配置模型 NacosServerSettings.java 与application.yml还额外提供了 Nacos 认证相关的四个字段:
| 参数 | 环境变量覆盖 | 默认值 | 说明 |
|---|---|---|---|
username | SW_CONFIG_NACOS_USERNAME | 空 | Nacos 认证用户名 |
password | SW_CONFIG_NACOS_PASSWORD | 空 | Nacos 认证密码 |
accessKey | SW_CONFIG_NACOS_ACCESSKEY | 空 | 阿里云 ACM / 鉴权 AccessKey |
secretKey | SW_CONFIG_NACOS_SECRETKEY | 空 | 与 AccessKey 配套的 SecretKey |
在启动阶段,NacosConfigurationProvider.java 会对配置做合法性校验:
serverAddr为空或 null → 抛出ModuleStartException("Nacos serverAddr cannot be null or empty.");port <= 0→ 抛出ModuleStartException("Nacos port must be positive integer.");group为空 → 抛出ModuleStartException("Nacos group cannot be null or empty.");username与accessKey同时非空→ 抛出ModuleStartException("Nacos Auth method should choose either username or accessKey, not both"),即两种认证方式只能二选一。
校验通过后,initConfigReader()构造NacosConfigWatcherRegister并交由模块框架启动(该模块依赖com.alibaba.nacos:nacos-client,见 configuration-nacos/pom.xml)。
三、Nacos 中的配置存储模型
启用后,OAP 会以Data Id = 配置键(configKey)、Group = 上面配置的group的方式读写 Nacos 配置。依据配置类型的不同,分为 Single 与 Group 两种存储形态。
3.1 Single 单值配置
Single 配置是一个配置键对应一个配置值,逻辑结构为{configKey}:{configValue},在 Nacos 中的存储结构为:
| Data Id | Group | Config Value |
|---|---|---|
| configKey | {group} | configValue |
例如动态配置为:
{agent-analyzer.default.slowDBAccessThreshold}:{default:200,mongodb:50}当group = skywalking时,Nacos 中的实际配置为:
| Data Id | Group | Config Value |
|---|---|---|
| agent-analyzer.default.slowDBAccessThreshold | skywalking | default:200,mongodb:50 |
在 Nacos 控制台的「配置管理 → 配置列表」中新建一条配置,Data ID 填agent-analyzer.default.slowDBAccessThreshold,Group 填skywalking,配置内容填default:200,mongodb:50即可完成下发;该配置将覆盖application.yml中agent-analyzer/default/slowDBAccessThreshold的值。
3.2 Group 组配置
Group 配置是一个配置键对应一组「子键-子值」,在 Nacos 中的存储结构为:
| Data Id | Group | Config Value | Config Type |
|---|---|---|---|
| configKey | {group} | subItemkey1 subItemkey2 ... | TEXT |
| subItemkey1 | {group} | subItemValue1 | |
| subItemkey2 | {group} | subItemValue2 | |
| ... | ... | ... |
即:主配置项(Data Id 为 configKey)的内容是一个子键清单,每个子键又各自是一条独立的配置(Data Id 为 subItemkey)。若需新增/删除某个子项,必须同步更新主配置项里的子键清单。
子键之间的分隔规则为:
- 通过Nacos UI设置时,每个子键独占一行(行与行之间以
\n分隔),前后空白会被自动 trim:
subItemValue1 subItemValue2 ...- 通过Nacos Open API / SDK发布时,子键以
\n或\r\n分隔,例如:
configService.publishConfig("test-module.default.testKeyGroup", "skywalking", "subItemkey1\n subItemkey2"));这与源码中 NacosConfigWatcherRegister.java 的解析逻辑一致:readGroupConfig对主配置内容执行config.split("\\n|\\r\\n")后对每个子键做String::trim,再逐一getConfig(itemName, group, 1000)拉取子键的值。
例如动态配置为:
{core.default.endpoint-name-grouping-openapi}:|{customerAPI-v1}:{value of customerAPI-v1} |{productAPI-v1}:{value of productAPI-v1} |{productAPI-v2}:{value of productAPI-v2}当group = skywalking时,Nacos 中的实际配置为:
| Data Id | Group | Config Value | Config Type |
|---|---|---|---|
| core.default.endpoint-name-grouping-openapi | skywalking | customerAPI-v1 productAPI-v1 productAPI-v2 | TEXT |
| customerAPI-v1 | skywalking | value of customerAPI-v1 | |
| productAPI-v1 | skywalking | value of productAPI-v1 | |
| productAPI-v2 | skywalking | value of productAPI-v2 |
core.default.endpoint-name-grouping-openapi用于为不同服务下发 OpenAPI 定义文件(YAML 内容),子键按serviceName.文件名组织,从而生成端点名分组规则(参见 endpoint-grouping-rules.md)。
四、同步与监听:configuration-nacos 模块源码解析
Nacos 动态配置的核心实现位于 NacosConfigWatcherRegister.java,它继承自FetchingConfigWatcherRegister(configuration-api 模块),整体运行机制分三层:
1. 连接建立(构造阶段)
构造函数将serverAddr:port、namespace以及可选的username/password或accessKey/secretKey写入Properties,并通过NacosFactory.createConfigService(properties)创建 NacosConfigService客户端(PropertyKeyConst.SERVER_ADDR、PropertyKeyConst.NAMESPACE、PropertyKeyConst.USERNAME/PASSWORD、PropertyKeyConst.ACCESS_KEY/SECRET_KEY)。
2. 周期全量同步(Fetching)
FetchingConfigWatcherRegister.start()会启动一个单线程调度器,以syncPeriod(即配置项period,默认 60 秒)为周期执行configSync(),内部依次调用singleConfigsSync()与groupConfigsSync():前者对每个已注册的WatchType.SINGLE监听器调用readConfig(keys),后者对WatchType.GROUP监听器调用readGroupConfig(keys),并将拉取结果写入ConfigTable/GroupConfigTable,最终回调各ConfigChangeWatcher完成值更新(详见 FetchingConfigWatcherRegister.java)。
3. Nacos 实时监听(Push)
readConfig内部先通过removeUninterestedKeys(keys)移除已失效的监听,再对每个 Data Id 调用configService.addListener(dataId, group, listener)注册监听器;监听器触发时执行onDataIdValueChanged(dataId, configInfo),把新值写入configItemKeyedByName缓存并打印Nacos config changed日志。对于新注册的键,还会立即getConfig(dataId, group, 1000)拉取一次初值,从而兼顾「实时推送」与「启动即生效」两条路径(registerKeyListeners)。
五、支持动态化的配置项速览
并非所有 OAP 配置都支持动态下发,可动态化的键由各模块在启动时注册到ConfigWatcherRegister。以下为当前支持的核心键(详见 dynamic-config.md):
Single 单值配置:
| Config Key | 值说明 | 值格式示例 |
|---|---|---|
agent-analyzer.default.slowDBAccessThreshold | 慢数据库语句阈值,覆盖application.yml中agent-analyzer/default/slowDBAccessThreshold | default:200,mongodb:50 |
agent-analyzer.default.uninstrumentedGateways | 未插桩网关配置,覆盖gateways.yml | 同 uninstrumented-gateways.md |
alarm.default.alarm-settings | 告警规则,覆盖alarm-settings.yml | 同 backend-alarm.md |
core.default.apdexThreshold | Apdex 阈值,覆盖service-apdex-threshold.yml | 同 apdex-threshold.md |
core.default.endpoint-name-grouping | 端点名分组规则,覆盖endpoint-name-grouping.yml | 同 endpoint-grouping-rules.md |
core.default.log4j-xml | log4j 日志配置,覆盖log4j2.xml | 同 dynamical-logging.md |
core.default.searchableTracesTags | 可检索的 Trace Tag 列表,覆盖application.yml中core/default/searchableTracesTags | http.method,http.status_code,rpc.status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker |
agent-analyzer.default.traceSamplingPolicy | 默认与按服务维度的采样策略,覆盖trace-sampling-policy-settings.yml | 同 trace-sampling.md |
configuration-discovery.default.agentConfigurations | ConfigurationDiscovery 配置 | 见 Java Agent 的 configuration-discovery 说明 |
Group 组配置:
| Config Key | 子键说明 | 值说明 |
|---|---|---|
core.default.endpoint-name-grouping-openapi | 与 OpenAPI 定义文件相关的服务名,如serviceA;一个服务对应多个文件时,子键用serviceName.文件名拆分,如serviceA.API-file1、serviceA.API-file2 | OpenAPI 定义文件内容(YAML 格式),用于生成端点名分组规则,格式同 endpoint-grouping-rules.md |
以 Nacos 下发agent-analyzer.default.slowDBAccessThreshold为例,在 Nacos 控制台发布后,OAP 无需重启即可在下一个同步周期(或通过监听实时)感知变更,动态调整慢 SQL 统计阈值;同理可动态下发告警规则与端点分组规则。
六、集成测试验证:NacosConfigurationIT
仓库为 Nacos 动态配置提供了基于 Testcontainers 的集成测试 NacosConfigurationIT.java,可直接作为功能验证的参考:
- 测试环境:
nacos/nacos-server:v2.3.2-slim容器,MODE=standalone,暴露8848(HTTP)与9848(gRPC 端口,测试中通过nacos.server.grpc.port.offset设置偏移); - Single 验证:向
test-module.default.testKey(Groupskywalking)发布值500,等待provider.watcher.value()变为500;随后removeConfig删除该键,验证值恢复为 null —— 覆盖「新增生效、删除失效」两条路径; - Group 验证:向
test-module.default.testKeyGroup发布"item1\n item2",并分别发布item1=100、item2=200,验证组内各子项被正确解析加载;随后依次删除item1、修改item1=300、删除主键testKeyGroup,验证组配置的增、删、改全流程与主键清单的联动(shouldReadUpdatedGroup)。
此外,单元测试 NacosConfigWatcherRegisterTest.java 与测试模块NacosConfigurationTestModule/NacosConfigurationTestProvider共同构成了对该实现的回归保障。
七、使用注意事项
- 默认关闭:动态配置依赖外部配置中心,
configuration.selector默认是none,未显式切换到nacos前不会建立 Nacos 连接; - 同步周期与实时性:
period(默认 60 秒)控制周期全量同步频率,同时 Nacos 监听器提供实时推送,实际生效速度通常远快于一个周期;缩短period可加速兜底同步,但会增加对 Nacos 的轮询压力; - Group 子键维护:新增/删除子项时,务必同步更新主配置项(configKey)中的子键清单,否则子项不会被加载;子键之间以换行分隔,前后空白会被 trim,主配置项文本末尾的空行可忽略;
- 认证方式互斥:
username/password与accessKey/secretKey只能选择其一,同时配置会导致 OAP 启动失败; - Data Id 与 Group 强绑定:所有读写均使用
configuration.nacos.group指定的 Group(默认skywalking),在 Nacos 控制台新建配置时 Group 必须与此一致,否则无法命中。
- 可观测性
- 后端
- 微服务
- 云原生
【免费下载链接】skywalking
APM, Application Performance Monitoring System
相关推荐
Apache SkyWalking 动态配置(Dynamic Configuration)机制详解:从 application.yml 开关到 ZooKeeper/Etcd/Nacos 多实现
Apache SkyWalking 动态配置(Dynamic Configuration)机制详解:从 application.yml 开关到 ZooKeepe
可观测性后端微服务云原生RuoYi-Vue-fast配置中心实现:Nacos集成与动态配置
RuoYi Vue fast配置中心实现:Nacos集成与动态配置 你是否还在为项目配置修改需要重启服务而烦恼?是否希望实现配置的实时更新而不影响系统运行?本文
告别配置地狱:SeaTunnel集成动态配置中心实战指南
告别配置地狱:SeaTunnel集成动态配置中心实战指南 你是否还在为数据同步任务中的配置变更焦头烂额?每次修改配置文件后重启集群的操作不仅繁琐,还可能导致数据
数据工程大数据批处理流处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考