Apache SkyWalking OAP 后端动态配置:ZooKeeper 实现完整指南
Apache SkyWalking OAP 后端动态配置ZooKeeper 实现完整指南【免费下载链接】skywalkingAPM, Application Performance Monitoring System项目地址: https://gitcode.com/gh_mirrors/sk/skywalkingApache SkyWalking 的 OAP 后端允许将部分配置项从application.yml与 OS 环境变量中抽离出来交由上游配置管理中心Dynamic Configuration Center, DCC动态下发与热更新。ZooKeeper 是官方支持的实现之一。本篇指南围绕 dynamic-config-zookeeper.md 展开讲解如何启用 ZooKeeper 作为动态配置中心、每个配置参数的含义与默认值、配置项在 ZooKeeper 节点中的存储结构Single 与 Group 两种形态并结合仓库源码说明其底层同步与失效机制。读完本文你将能够在自己的 SkyWalking 部署中通过 ZooKeeper 实现告警规则、采样策略、慢 SQL 阈值等配置的免重启热更新。动态配置能力本身依赖上游服务默认是关闭的。本文介绍的是其中 ZooKeeper 一种实现其余实现DCS、Etcd、Consul、Apollo、Kubernetes Configmap、Nacos见 Dynamic Configuration 总览文档。一、功能定位与启用方式SkyWalking 的大多数配置通过 application.yml 和系统环境变量设置但其中一部分支持动态配置即运行时由外部配置中心下发、OAP 周期拉取并应用无需重启进程。该功能由configuration模块承载selector决定使用哪一种配置中心实现。在 application.yml 中ZooKeeper 实现的默认配置块如下与官方文档完全一致configuration: selector: ${SW_CONFIGURATION:zookeeper} zookeeper: period: ${SW_CONFIG_ZK_PERIOD:60} # Unit seconds, sync period. Default fetch every 60 seconds. namespace: ${SW_CONFIG_ZK_NAMESPACE:/default} hostPort: ${SW_CONFIG_ZK_HOST_PORT:localhost:2181} # Retry Policy baseSleepTimeMs: ${SW_CONFIG_ZK_BASE_SLEEP_TIME_MS:1000} # initial amount of time to wait between retries maxRetries: ${SW_CONFIG_ZK_MAX_RETRIES:3} # max number of times to retry把selector切换为zookeeper或通过环境变量SW_CONFIGURATIONzookeeper即完成启用。若未配置任何动态配置中心则保持默认的selector: ${SW_CONFIGURATION:none}动态配置功能处于关闭状态。参数速查表参数环境变量默认值说明periodSW_CONFIG_ZK_PERIOD60同步周期单位秒默认每 60 秒拉取一次namespaceSW_CONFIG_ZK_NAMESPACE/defaultZooKeeper 命名空间即配置根节点路径hostPortSW_CONFIG_ZK_HOST_PORTlocalhost:2181ZooKeeper 集群地址支持host1:port1,host2:port2形式baseSleepTimeMsSW_CONFIG_ZK_BASE_SLEEP_TIME_MS1000重试策略的初始等待时间毫秒即每次重试之间等待的初始时长maxRetriesSW_CONFIG_ZK_MAX_RETRIES3最大重试次数从源码 ZookeeperServerSettings.java 可以看到这些默认值在 Java 侧的对应定义namespace /default、baseSleepTimeMs 1000、maxRetries 3、period 60其中hostPort未设默认值必须显式配置。启动校验逻辑在 ZookeeperConfigurationProvider.java 的initConfigReader()中OAP 启动时会校验配置合法性hostPort为空或 null 时抛出ModuleStartException(Zookeeper hostPort cannot be null or empty.)namespace为空或 null 时抛出ModuleStartException(Zookeeper namespace cannot be null or empty.)校验通过后创建ZookeeperConfigWatcherRegister实例任何异常如无法连接 ZooKeeper都会以ModuleStartException形式终止启动。这意味着一旦selector选择 zookeeperOAP 启动时就会建立与 ZooKeeper 的连接连接失败将直接导致模块启动失败。二、namespace配置的根路径语义文档中明确说明namespace 就是 ZooKeeper 路径znode path配置的 key 与 value 是 namespace 目录下的属性。在 ZookeeperConfigWatcherRegister.java 构造方法中可以看到具体实现prefix settings.getNamespace() /; RetryPolicy retryPolicy new ExponentialBackoffRetry(settings.getBaseSleepTimeMs(), settings.getMaxRetries()); this.client CuratorFrameworkFactory.newClient(settings.getHostPort(), retryPolicy); client.start(); this.childrenCache new PathChildrenCache(client, settings.getNamespace(), true); this.childrenCache.start();要点重试策略使用 Curator 的ExponentialBackoffRetry指数退避重试初始等待时间取baseSleepTimeMs重试次数取maxRetries本地缓存通过PathChildrenCache监听 namespace 路径下的子节点true参数表示启动时同时缓存子节点数据因此每次读取走本地缓存不阻塞于网络读取键readConfig()中通过childrenCache.getCurrentData(prefix key)拼接出完整节点路径prefix即namespace /后取数据数据以 UTF-8 解码为字符串。三、Single Config单值配置的存储结构单值配置的逻辑结构是{configKey}:{configValue}。映射到 ZooKeeper 为znode.path {namespace}/configKey configValue znode.data官方文档示例配置{agent-analyzer.default.slowDBAccessThreshold}:{default:200,mongodb:50}当namespace /default时znode.path /default/agent-analyzer.default.slowDBAccessThreshold znode.data default:200,mongodb:50即节点路径 namespace / configKey节点数据 configValue。可以用zkCli.sh或任意 ZooKeeper 客户端创建create /default/agent-analyzer.default.slowDBAccessThreshold default:200,mongodb:50源码验证单元测试 ZookeeperConfigWatcherRegisterTestCase.java 模拟了namespace /default、key agent-analyzer.default.slowDBAccessThreshold、value default:100,mongodb:50的场景验证readConfig()能从PathChildrenCache中正确取出该键值对。集成测试 ZookeeperConfigurationIT.java 则真实启动zookeeper:3.9容器验证创建节点/default/test-module.default.testKey数据500后watcher 的值由 null 变为500删除节点后watcher 的值又回归 null——完整印证了创建即生效、删除即失效的行为。四、Group Config分组配置的存储结构分组配置的逻辑结构是一个 configKey 对应一组子配置项每个子项是一个 key-value 对{configKey}: |{subItemkey1}:{subItemValue1} |{subItemkey2}:{subItemValue2} ...映射到 ZooKeeper 为znode.path {namespace}/configKey znode.child1.path {znode.path}/subItemkey1 znode.child2.path {znode.path}/subItemkey2 ... subItemValue1 znode.child1.data subItemValue2 znode.child2.data官方文档示例配置{core.default.endpoint-name-grouping-openapi}下挂三个子项customerAPI-v1、productAPI-v1、productAPI-v2当namespace /default时znode.path /default/core.default.endpoint-name-grouping-openapi znode.customerAPI-v1.path /default/core.default.endpoint-name-grouping-openapi/customerAPI-v1 znode.productAPI-v1.path /default/core.default.endpoint-name-grouping-openapi/productAPI-v1 znode.productAPI-v2.path /default/core.default.endpoint-name-grouping-openapi/productAPI-v2 znode.customerAPI-v1.data value of customerAPI-v1 znode.productAPI-v1.data value of productAPI-v1 znode.productAPI-v2.data value of productAPI-v2即父节点路径 namespace / configKey父节点本身不存数据每个子节点路径 父节点路径 / subItemKey子节点数据 subItemValue。创建命令示例create /default/core.default.endpoint-name-grouping-openapi create /default/core.default.endpoint-name-grouping-openapi/customerAPI-v1 value of customerAPI-v1 create /default/core.default.endpoint-name-grouping-openapi/productAPI-v1 value of productAPI-v1 create /default/core.default.endpoint-name-grouping-openapi/productAPI-v2 value of productAPI-v2源码验证ZookeeperConfigWatcherRegister.java 的readGroupConfig()使用 Curator 的client.getChildren().forPath(prefix key)枚举父节点下的所有子节点名再对每个子节点调用client.getData().forPath(...)读取数据组装为GroupConfigTable.GroupConfigItems。与单值配置走本地缓存不同分组配置的每个子节点数据是实时向 ZooKeeper 发请求读取的。集成测试shouldReadUpdated4GroupConfig验证了该路径创建/default/test-module.default.testKeyGroup/item1数据100与item2数据200后watcher 的分组项依次出现item1、item2删除两个子节点后分组项又恢复为空。五、底层工作机制拉取式同步与 Watcher 注册ZooKeeper 实现继承自 FetchingConfigWatcherRegister.java核心机制是周期拉取polling而非 ZooKeeper 的事件推送注册各业务模块在启动阶段调用registerConfigChangeWatcher()将ConfigChangeWatcher注册进来。每个 watcher 都有唯一 key即 configKey并按WatchType分为SINGLE与GROUP两类分别存入两个独立的注册表重复注册同一 key 会抛出IllegalStateException。启动start()方法启动一个名为ConfigWatcherSync的守护线程单线程调度器通过scheduleAtFixedRate以syncPeriod即period配置默认 60 秒为间隔周期执行configSync()异常由RunnableWithExceptionProtection捕获并记录日志不会中断后续同步。同步configSync()依次执行singleConfigsSync()与groupConfigsSync()先调用readConfig(keys)/readGroupConfig(keys)拉取当前值再逐项找到对应的 watcher 并回调通知。若配置中心返回的 key 没有匹配到任何 watcher会打印 warn 日志并忽略。生命周期上AbstractConfigurationProvider.java 定义了通用骨架prepare()中调用子类的initConfigReader()并注册DynamicConfigurationService服务notifyAfterCompleted()中才真正调用configWatcherRegister.start()启动周期同步——确保所有模块完成启动、watcher 注册完毕后再开始拉取配置。从源码结构看这一注册-周期拉取-回调通知的模型是所有动态配置实现ZooKeeper、Etcd、Consul、Apollo、Nacos、Kubernetes Configmap、DCS共用的抽象骨架ZooKeeper 实现只负责readConfig/readGroupConfig两个抽象方法的落地。六、实际可用的动态配置项启用 ZooKeeper 动态配置后以下官方支持的配置项均可通过前述存储结构下发完整清单见 Dynamic Configuration配置 Key说明agent-analyzer.default.slowDBAccessThreshold慢数据库语句阈值覆盖application.yml中同名配置agent-analyzer.default.uninstrumentedGateways未接入探针的网关覆盖 gateways.yml 对应文档alarm.default.alarm-settings告警设置覆盖 alarm-settings.ymlcore.default.apdexThresholdApdex 阈值覆盖 service-apdex-threshold.ymlcore.default.endpoint-name-grouping端点名分组规则覆盖 endpoint-name-grouping.ymlcore.default.log4j-xmllog4j XML 配置覆盖 log4j2.xmlcore.default.searchableTracesTags可搜索的 Trace 标签agent-analyzer.default.traceSamplingPolicy采样策略覆盖 trace-sampling-policy-settings.ymlcore.default.endpoint-name-grouping-openapi分组配置OpenAPI 定义文件内容用于生成端点名分组规则子项 key 需以serviceName.fileName形式命名七、最佳实践与注意事项先建父节点再建子节点分组配置的父节点需预先创建数据可为空否则创建子节点可能失败Curator 客户端侧可用creatingParentsIfNeeded()自动补建父节点集成测试即采用该方式。删除即恢复默认从集成测试可以看到删除 znode 后 watcher 值回归 nullOAP 相应配置会回落到本地默认值。可利用这一点实现临时调优后一键回滚。同步延迟单值配置读取依赖PathChildrenCache本地缓存实际生效时间受period默认 60 秒与缓存刷新时机共同影响需要更快的生效速度可调小period但会增加对 ZooKeeper 的访问频率。连接与重试OAP 启动时必须能连通 ZooKeeper运行期若 ZooKeeper 短暂不可用ExponentialBackoffRetry与RunnableWithExceptionProtection会兜底重试与异常保护避免同步线程崩溃。多实例一致性集群部署时各 OAP 实例独立周期拉取同一 ZooKeeper 命名空间配置天然一致更新配置只需操作 ZooKeeper 节点无需逐个实例修改本地文件。命名空间隔离通过不同的namespace如/default、/prod可在同一 ZooKeeper 集群内隔离多套环境或集群的配置。八、参考阅读动态配置总览与完整配置项清单docs/en/setup/backend/dynamic-config.mdZooKeeper 实现源码ZookeeperConfigWatcherRegister.java、ZookeeperConfigurationProvider.java、ZookeeperServerSettings.java通用抽象骨架FetchingConfigWatcherRegister.java、AbstractConfigurationProvider.java测试用例ZookeeperConfigurationIT.java、ZookeeperConfigWatcherRegisterTestCase.java其他动态配置实现Etcddynamic-config-etcd.md、Consuldynamic-config-consul.md、Apollodynamic-config-apollo.md、Nacosdynamic-config-nacos.md、Kubernetes Configmapdynamic-config-configmap.md、DCSdynamic-config-service.md【免费下载链接】skywalkingAPM, Application Performance Monitoring System项目地址: https://gitcode.com/gh_mirrors/sk/skywalking创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考