侧边栏壁纸
  • 累计撰写 228 篇文章
  • 累计创建 244 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

从 Git 托管 YAML 到 Nacos:一次面向运维实践与架构演进的微服务治理改造复盘

zhanjie.me
2026-02-05 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

这是“微服务治理”系列的第一篇。
这一篇先回答一个更底层的问题:当系统进入微服务阶段之后,为什么配置中心和注册中心不该再被当成两条彼此独立的线,而应该被放到同一个运行时治理框架里理解。

摘要

这次改造表面上看,是把配置从 Git 中的 YAML 文件迁移到了 Nacos,并把 Dubbo 注册中心从 Zookeeper 统一到了 Nacos;但如果只把它理解成一次中间件替换,意义其实被低估了。真正发生变化的,不只是配置搬了个地方,而是微服务系统第一次开始围绕统一的运行时边界来组织配置、注册、环境隔离和发布切换。本文会从运维实践和架构演进两个角度,复盘这次改造为什么发生、为什么选择 Nacos,以及它为什么会成为后续 Kubernetes、网关流量治理、蓝绿灰度发布和可观测平台建设的起点。

系列导航

正文

一、改造背景:问题不在 YAML,而在治理边界

在很多团队的早期微服务实践里,把配置文件和代码一起放在 Git 仓库中统一管理,其实是一种很自然的选择。

这种方式简单、直接,也符合研发团队最熟悉的工作流:配置有版本记录,变更能进入 CI/CD 流程,出了问题也能顺着提交记录回溯。对于服务数量不多、环境不复杂、配置变更频率也不高的阶段来说,这样做并没有什么问题。

但当系统逐渐进入微服务阶段之后,问题开始慢慢显现出来。

这时候,配置已经不再只是工程目录中的一个 YAML 文件,而是开始直接参与服务运行本身。数据库连接方式、中间件接入参数、Dubbo 相关配置、环境差异、发布切换,这些内容本质上都已经属于运行时边界的一部分。如果仍然继续把它们附着在代码仓库和工程制品上,表面上看是“统一管理”,实际上却意味着配置治理始终没有真正独立出来。

最先暴露出来的是配置边界问题。数据库、中间件、第三方依赖接入方式,甚至部分认证相关参数,本质上已经属于运行时敏感配置。但在 Git 托管 YAML 的模式下,这些内容和普通业务配置往往混放在一起,配置治理天然依附在代码仓库权限模型之上。这样做在早期并不显得突兀,但随着系统复杂度上升,它会让敏感配置和业务代码之间的边界越来越模糊。

其次,配置变更和应用发布被天然绑在了一起。改一个配置,往往意味着提交流水线、重新打包、重新发布。早期这样看起来流程统一,但到了微服务阶段,这种方式会把很多本该属于“配置治理”的动作放大成一次完整的版本发布。配置回滚、问题排查、运维部署管理,也会因此变得更重。

再往后,多环境问题开始变得复杂。生产、测试、联调、蓝绿,这些环境一旦并存,仅靠多份配置文件和人工约定去维持差异,成本会越来越高。问题不在于文件够不够多,而在于系统是否具备一套明确的环境表达模型。如果环境边界只能藏在文件命名、目录结构、脚本参数甚至人的经验里,那么它就很难支撑后续的平台化演进。

更关键的是,在微服务体系里,服务能否稳定运行,并不只取决于本地配置是否正确,还取决于服务最后注册到哪里、又会被谁发现。

也就是说,系统运行时实际上同时存在两件同样重要的事:

  • 服务怎么跑
  • 服务在哪里被发现

如果这两件事分别由两套彼此割裂的模型承接,那么环境隔离、蓝绿切换、发布治理最终都只能做到局部成立,而很难形成真正的运行时闭环。

图 1:从 Git 托管 YAML 到 Nacos 的治理模型变化

图 1:旧模式的问题不在 YAML 本身,而在治理边界分散;Nacos 改造的本质,是把配置治理与注册治理收敛到统一运行时模型中。

二、为什么选择 Nacos:我们需要的不是新工具,而是统一治理模型

这次选择 Nacos,并不是单纯因为它“可以做配置中心”,也不是因为“Dubbo 支持它做注册中心”,而是因为它刚好能把我们最关心的两类运行时能力,收敛到同一套治理语义下。

一类是配置治理。

我们的微服务基于 Spring Boot 开发,通过接入 Nacos 配置能力,让服务启动阶段所依赖的配置从工程文件里抽离出来,变成独立的运行时配置对象。这个变化看似只是配置换了个地方,实际上是在重构配置与制品之间的关系。配置第一次不再默认附着在代码仓库里,而开始拥有自己的环境边界、变更边界和组织方式。

另一类是注册治理。

在 Dubbo 场景下,注册中心从来不只是一个“记一下地址”的地方。它实际决定的是:服务实例注册到哪里,消费者最终又会发现哪一组 provider。如果这层边界没有治理清楚,那么即使配置已经按环境隔离,运行时仍然可能发生跨环境发现、蓝绿边界失真、测试与生产相互干扰。

而 Nacos 的价值,恰恰在于它能同时承接这两件事。

一边,它把“服务怎么跑”这件事纳入配置中心治理;另一边,它又把“服务在哪里被发现”这件事纳入注册中心治理。更重要的是,这两件事不是彼此独立的,而是可以围绕同一套环境模型组织起来。

在我们的实践里,Nacos 中的 namespacegroup 并不只是参数,而是环境治理模型的一部分。

  • namespace 负责更粗粒度的环境隔离
  • group 负责同一环境内部更细粒度的逻辑分组

此外,Nacos 也很适合微服务场景下常见的配置分层需求。很多配置天然属于公共能力,比如数据库和中间件接入、Dubbo 公共参数、基础设施相关约定;另一些配置则只属于当前服务自身。把这些内容拆开治理,再按需组合引用,比让每个服务都维护一整份完整配置更适合长期演进。

图 2:Nacos 在微服务体系中的双重角色

图 2:Nacos 在这里不是单一配置工具,而是同时承担“服务怎么跑”和“服务在哪里被发现”两类治理职责。

三、Nacos 作为配置中心:从文件托管到运行时配置治理

如果说从 Git 托管 YAML 迁移到 Nacos,最直观的变化是配置不再跟着代码一起走,那么更深一层的变化其实是:配置开始从工程文件的一部分,变成服务运行时的一部分。

在我们的微服务体系中,Spring Boot 服务通过接入 Nacos 配置能力,在启动阶段从 Nacos 加载配置。这里最重要的,并不是“支持从远端读配置”这件事本身,而是服务启动时所依赖的配置装配,第一次进入了一套可治理、可分层、可隔离的运行时模型。

在实践里,我们会把配置拆成两类:

  • 公共配置
  • 服务专用配置

公共配置承载数据库、中间件、Dubbo 公共参数等基础能力;服务专用配置只保留当前服务自身真正关心的业务运行参数。服务启动时,再通过组合引用的方式,把这些能力拼装成最终运行时所需的配置视图。

spring:
  application:
    name: order-service

nacos:
  config:
    server-addr: ${NACOS_ADDR}
    namespace: ${NACOS_CONFIG_NS}
    auto-refresh: false
    bootstrap:
      enable: true
    extension-configs:
      - data-id: common-datasource.yaml
        group: DEFAULT_GROUP
        refresh: false
      - data-id: common-middleware.yaml
        group: DEFAULT_GROUP
        refresh: false
      - data-id: order-service.yaml
        group: DEFAULT_GROUP
        refresh: false

这样做的价值,并不只是“少写几份重复 YAML”,而是把配置治理从“文件复制”推进到了“逻辑组合”。

它带来的直接收益包括:

  • 公共能力可以统一维护
  • 服务侧配置更聚焦
  • 环境差异更容易表达
  • 配置漂移更容易控制

在这里,我们也比较看重配置优先级和 override 机制。很多时候,配置治理并不是追求“所有参数都只能在一个地方改”,而是希望建立一套清晰可解释的优先级规则:哪些参数由配置中心统一管理,哪些参数允许部署侧在特定环境下进行覆盖。这样既能保持统一治理,又不会把部署管理做得过于僵硬。

另一个我们刻意保持保守的点,是 refresh。动态刷新从功能上看很方便,但从稳定性角度看,并不是所有配置都适合无边界热更新。对于运行时行为敏感、依赖初始化复杂或者变更风险较高的场景,默认保守反而更符合运维治理诉求。

四、Nacos 作为注册中心:让环境边界进入服务发现层

如果说配置中心解决的是“服务怎么跑”,那么注册中心解决的就是另一件同样关键的事:服务应该在哪里被发现,以及它应该被哪一组消费方发现。

在 Dubbo 微服务体系里,这个问题非常重要。因为微服务的运行边界,并不只取决于本地参数配置是否正确,还取决于 provider 和 consumer 在运行时究竟是如何建立连接关系的。

所以,把注册中心从 Zookeeper 统一到 Nacos,意义并不只是“换了一个注册中心选型”。更重要的变化在于,配置治理和注册治理开始围绕同一套环境语义来组织。

在注册中心侧,我们更倾向于这样理解:

  • namespace 用来承接更大尺度的环境隔离
  • group 用来承接同一环境内部的逻辑运行面
NACOS_REGISTRY_NS=prod-namespace

dubbo.registry.address: nacos://${NACOS_HOST:-}:8848?username=${NACOS_USERNAME:nacos}&password=${NACOS_PASSWORD:nacos}&namespace=${NACOS_REGISTRY_NS:9f9378ca-c90e-449d-8a9b-875f2db71f48}

-Ddubbo.registry.group=DEFAULT_GROUP
-Ddubbo.registry.group=BLUE_GROUP

这也是为什么我们会把蓝绿边界显式带进注册治理里,而不是只停留在网关层。因为网关层解决的是外部请求先进入哪一套入口,而注册中心解决的是服务消费方在内部最终会发现哪一组 provider。

图 3:namespace 与 group 如何共同表达运行时环境边界

图 3:namespace 负责更粗粒度的环境隔离,group 负责同环境内部更细粒度的逻辑切分,两者组合起来,才能让蓝绿边界深入到服务发现层。

五、从运维实践看,这次改造到底解决了什么

如果站在运维实践角度回看这次改造,最直接的收益不是“改配置更方便了”,而是运行时开始变得更可治理了。

首先,配置安全边界开始独立出来。敏感配置不再默认跟着代码仓库一起流转,配置对象第一次拥有了相对独立的管理边界。

其次,配置变更不再默认等于一次应用发布。配置和版本之间开始拥有更清晰的分工边界,团队终于可以更明确地区分哪些变化属于配置治理,哪些变化属于版本演进。

再次,多环境治理从“文件复制”逐渐走向“逻辑隔离”。环境不再主要靠文件命名和人工约定来维持,而开始通过 namespacegroup、公共配置和服务专用配置这些模型来表达。

最后,发布治理开始拥有更稳定的前提。无论是蓝绿还是灰度,真正稳定的基础都不是“入口切流做得多漂亮”,而是运行时边界是否已经清晰。

六、从架构演进看,为什么它是后续平台化建设的起点

从架构演进角度看,这次改造最重要的意义在于,它不是终点,而是后续很多平台能力建设的起点。

当系统继续向 Kubernetes 演进时,镜像不可变、环境差异运行时表达会变得越来越重要。如果配置仍然附着在工程制品里,注册边界也没有统一模型,那么容器化只是把旧问题换了一个承载平台。

当系统继续往 APISIX、Ingress、服务网关和流量治理演进时,入口层边界也需要和服务发现层边界保持一致。网关负责的是请求怎么进来,注册中心负责的是请求进来之后服务之间如何继续维持环境隔离。两者不是替代关系,而是前后衔接关系。

再往后,无论是蓝绿灰度发布、三层可观测体系,还是更标准化的 CI/CD 与 GitOps 交付,都需要建立在一套更稳定的运行时骨架之上。
图 4:Nacos 改造不是终点,而是后续平台能力建设的起点

图 4:配置治理与注册治理一旦统一建模,Kubernetes、网关流量治理、发布治理、可观测和交付体系就有了更稳定的运行时骨架。

七、结语

回头看这次改造,真正被替换掉的,并不是某种配置存放方式,而是一种已经不再适合微服务阶段的治理模型。

在早期阶段,把配置和代码一起放在 Git 里并没有问题;但当系统进入微服务、容器化和平台化演进阶段之后,配置已经不再只是工程文件,注册中心也不再只是实例登记。它们共同参与的是服务运行、环境隔离、发布切换和后续平台演进。

从这个角度看,Nacos 在这里的意义不只是“把配置从 Git 挪到了配置中心”,也不只是“把 Dubbo 注册统一到了 Nacos”,而是让配置治理和注册治理第一次围绕同一套环境模型组织起来。

从 Git 托管 YAML 到 Nacos,并不是把配置搬了个地方,而是把微服务从“文件管理 + 服务发现”推进到了“运行时治理”。

小结

这次改造最值得复盘的,不是用了哪个组件,而是系统第一次拥有了统一的运行时治理语义:

  • 配置中心定义服务怎么跑
  • 注册中心定义服务在哪里被发现
  • namespace + group 定义环境和运行面边界
  • 这些边界共同为容器化、网关治理、蓝绿发布和后续平台演进提供基础

延伸阅读

  • 后续我会继续写 ACK 微服务容器平台建设
  • APISIX 入口治理与蓝绿灰度发布
  • 指标、日志、链路三层可观测平台建设
  • 从 Jenkins 到 GitOps 的交付体系演进
  • AIOps / AI RCA 在故障分析中的落地实践
0

评论区