Skip to content

为什么要用配置中心?

微服务下,业务的发展一般会导致服务数量的增加,进而导致程序配置(服务地址、数据库参数等等)增多。传统的配置文件的方式已经无法满足当前需求,主要有下面几点原因:

  • 安全性得不到保障:配置放在代码库中容易泄露。
  • 时效性不行:修改配置需要重启服务才能生效。
  • 不支持权限控制 :没有对配置的修改、发布等操作进行严格的权限控制。
  • 不支持配置集中管理 : 配置文件过于分散,不方便管理。
  • ......

另外,配置中心通常会自带版本跟踪,会记录配置的修改记录,记录的内容包括修改人、修改时间、修改内容等等。

虽然通过 Git 版本管理我们也能追溯配置的修改记录,但是配置中心提供的配置版本管理功能更全面。并且,配置中心通常会在配置版本管理的基础上支持配置一键回滚。

一些功能更全面的配置中心比如Apollo甚至还支持灰度发布。

常见的配置中心有哪些?

Spring Cloud ConfigNacosApollo、K8s ConfigMap 、DisconfQconf 都可以用来做配置中心。

Disconf 和 Qconf 已经没有维护,生态也并不活跃,并不建议使用,在做配置中心技术选型的时候可以跳过。

如果你的技术选型是 Kubernetes 的话,可以考虑使用 K8s ConfigMap 来作为配置中心。

Apollo 和 Nacos 我个人更喜欢,两者都是国内公司开源的知名项目,项目社区都比较活跃且都还在维护中。Nacos 是阿里开源的,Apollo 是携程开源的。Nacos 使用起来比较简单,并且还可以直接用来做服务发现及管理。Apollo 只能用来做配置管理,使用相对复杂一些。

如果你的项目仅仅需要配置中心的话,建议使用 Apollo 。如果你的项目需要配置中心的同时还需要服务发现及管理的话,那就更建议使用 Nacos。

Spring Cloud Config 属于 Spring Cloud 生态组件,可以和 Spring Cloud 体系无缝整合。由于基于 Git 存储配置,因此 Spring Cloud Config 的整体设计很简单。

Apollo vs Nacos vs Spring Cloud Config

<table data-lake-id="76cb3044" id="76cb3044" margin="true" class="lake-table" style="width: 748px"><colgroup><col width="187"><col width="187"><col width="187"><col width="187"></colgroup><tbody><tr data-lake-id="u2e635725" id="u2e635725"><td data-lake-id="u60f2fb30" id="u60f2fb30"><p data-lake-id="u1e5ebb16" id="u1e5ebb16" style="text-align: left"><span data-lake-id="u6160e9f0" id="u6160e9f0">功能点</span></p></td><td data-lake-id="u9bf7658a" id="u9bf7658a"><p data-lake-id="u4622f1f9" id="u4622f1f9" style="text-align: left"><span data-lake-id="u31dd59cb" id="u31dd59cb">Apollo</span></p></td><td data-lake-id="ue1947dbc" id="ue1947dbc"><p data-lake-id="u8109c720" id="u8109c720" style="text-align: left"><span data-lake-id="u30e3f225" id="u30e3f225">Nacos</span></p></td><td data-lake-id="u0d842828" id="u0d842828"><p data-lake-id="u8c288cdb" id="u8c288cdb"><span data-lake-id="uacd50e24" id="uacd50e24">Spring Cloud Config</span></p></td></tr><tr data-lake-id="u1076d3a3" id="u1076d3a3"><td data-lake-id="u1ca81f2c" id="u1ca81f2c"><p data-lake-id="udb7fbed2" id="udb7fbed2" style="text-align: left"><span data-lake-id="u2a4560d2" id="u2a4560d2">配置界面</span></p></td><td data-lake-id="u59fbbf45" id="u59fbbf45"><p data-lake-id="uf55375c4" id="uf55375c4" style="text-align: left"><span data-lake-id="u687226b4" id="u687226b4">支持</span></p></td><td data-lake-id="ub4473095" id="ub4473095"><p data-lake-id="u10b11bb3" id="u10b11bb3" style="text-align: left"><span data-lake-id="u79718019" id="u79718019">支持</span></p></td><td data-lake-id="u126e30f0" id="u126e30f0"><p data-lake-id="uf75d1894" id="uf75d1894"><span data-lake-id="ub867a4ab" id="ub867a4ab">无(需要通过 Git 操作)</span></p></td></tr><tr data-lake-id="ueb6ca43a" id="ueb6ca43a"><td data-lake-id="u208c9ab4" id="u208c9ab4"><p data-lake-id="u52449738" id="u52449738" style="text-align: left"><span data-lake-id="u1be1ee48" id="u1be1ee48">配置实时生效</span></p></td><td data-lake-id="u18373659" id="u18373659"><p data-lake-id="ud0e6af98" id="ud0e6af98" style="text-align: left"><span data-lake-id="u74d8c137" id="u74d8c137">支持(HTTP 长轮询 1s 内)</span></p></td><td data-lake-id="uc2708ecb" id="uc2708ecb"><p data-lake-id="u5aca8d86" id="u5aca8d86" style="text-align: left"><span data-lake-id="ub769ceca" id="ub769ceca">支持(HTTP 长轮询 1s 内)</span></p></td><td data-lake-id="uc1a27c32" id="uc1a27c32"><p data-lake-id="uffdbe0ab" id="uffdbe0ab"><span data-lake-id="u1f5969f5" id="u1f5969f5">重启生效,或手动 refresh 生效</span></p></td></tr><tr data-lake-id="u6d6a759f" id="u6d6a759f"><td data-lake-id="u1ac191a8" id="u1ac191a8"><p data-lake-id="ube51d9ce" id="ube51d9ce" style="text-align: left"><span data-lake-id="u618e9e15" id="u618e9e15">版本管理</span></p></td><td data-lake-id="uf2ef6de4" id="uf2ef6de4"><p data-lake-id="u3a64ff47" id="u3a64ff47" style="text-align: left"><span data-lake-id="u920e9a40" id="u920e9a40">支持</span></p></td><td data-lake-id="ue7abd274" id="ue7abd274"><p data-lake-id="u87035fee" id="u87035fee" style="text-align: left"><span data-lake-id="u70b138bf" id="u70b138bf">支持</span></p></td><td data-lake-id="u403fc463" id="u403fc463"><p data-lake-id="u91e3cf55" id="u91e3cf55"><span data-lake-id="u343df0df" id="u343df0df">支持(依赖 Git)</span></p></td></tr><tr data-lake-id="u64b5df8f" id="u64b5df8f"><td data-lake-id="ue78ac835" id="ue78ac835"><p data-lake-id="uc3b1e102" id="uc3b1e102" style="text-align: left"><span data-lake-id="ue291538f" id="ue291538f">权限管理</span></p></td><td data-lake-id="ufb657729" id="ufb657729"><p data-lake-id="uae6f8d0a" id="uae6f8d0a" style="text-align: left"><span data-lake-id="u9564ec8f" id="u9564ec8f">支持</span></p></td><td data-lake-id="u8c8ca593" id="u8c8ca593"><p data-lake-id="u3fe8e226" id="u3fe8e226" style="text-align: left"><span data-lake-id="u43b1abc6" id="u43b1abc6">支持</span></p></td><td data-lake-id="u8f98a563" id="u8f98a563"><p data-lake-id="ud0a7fa8b" id="ud0a7fa8b"><span data-lake-id="u6649b2e3" id="u6649b2e3">支持(依赖 Git)</span></p></td></tr><tr data-lake-id="u02ae4ec0" id="u02ae4ec0"><td data-lake-id="u290949fd" id="u290949fd"><p data-lake-id="uec7fe55c" id="uec7fe55c" style="text-align: left"><span data-lake-id="ue21746a2" id="ue21746a2">灰度发布</span></p></td><td data-lake-id="u270780a3" id="u270780a3"><p data-lake-id="u72486b4e" id="u72486b4e" style="text-align: left"><span data-lake-id="ued88865e" id="ued88865e">支持</span></p></td><td data-lake-id="u0581676f" id="u0581676f"><p data-lake-id="u8920a433" id="u8920a433" style="text-align: left"><span data-lake-id="ud2558d09" id="ud2558d09">支持(Nacos 1.1.0 版本开始支持灰度配置)</span></p></td><td data-lake-id="u6b976c02" id="u6b976c02"><p data-lake-id="u00349db8" id="u00349db8"><span data-lake-id="ub033e500" id="ub033e500">不支持</span></p></td></tr><tr data-lake-id="u11468130" id="u11468130"><td data-lake-id="u5abf1092" id="u5abf1092"><p data-lake-id="u9fe2c14c" id="u9fe2c14c" style="text-align: left"><span data-lake-id="u0a694d39" id="u0a694d39">配置回滚</span></p></td><td data-lake-id="u8402f5a7" id="u8402f5a7"><p data-lake-id="uaad1b9e6" id="uaad1b9e6" style="text-align: left"><span data-lake-id="u4df693a9" id="u4df693a9">支持</span></p></td><td data-lake-id="ua3bffacc" id="ua3bffacc"><p data-lake-id="u43d18c33" id="u43d18c33" style="text-align: left"><span data-lake-id="u2db2883a" id="u2db2883a">支持</span></p></td><td data-lake-id="u1768f606" id="u1768f606"><p data-lake-id="u48571739" id="u48571739"><span data-lake-id="u4926fc01" id="u4926fc01">支持(依赖 Git)</span></p></td></tr><tr data-lake-id="uebe2166a" id="uebe2166a"><td data-lake-id="u37ddf230" id="u37ddf230"><p data-lake-id="ua8b0278c" id="ua8b0278c" style="text-align: left"><span data-lake-id="ubf3d16a7" id="ubf3d16a7">告警通知</span></p></td><td data-lake-id="u639e92ab" id="u639e92ab"><p data-lake-id="ub88f0bc3" id="ub88f0bc3" style="text-align: left"><span data-lake-id="ud3e3b04a" id="ud3e3b04a">支持</span></p></td><td data-lake-id="u38f04bdc" id="u38f04bdc"><p data-lake-id="u7ef4045e" id="u7ef4045e" style="text-align: left"><span data-lake-id="u7973f952" id="u7973f952">支持</span></p></td><td data-lake-id="u0799f754" id="u0799f754"><p data-lake-id="u3b87667b" id="u3b87667b"><span data-lake-id="u2ddfcefc" id="u2ddfcefc">不支持</span></p></td></tr><tr data-lake-id="ud76dccc4" id="ud76dccc4"><td data-lake-id="u7c507907" id="u7c507907"><p data-lake-id="ub3aef411" id="ub3aef411" style="text-align: left"><span data-lake-id="u6aff5360" id="u6aff5360">多语言</span></p></td><td data-lake-id="u64e099f8" id="u64e099f8"><p data-lake-id="u3317043a" id="u3317043a" style="text-align: left"><span data-lake-id="uef6ab76d" id="uef6ab76d">主流语言,Open API</span></p></td><td data-lake-id="ud8e395b1" id="ud8e395b1"><p data-lake-id="u0886a83c" id="u0886a83c" style="text-align: left"><span data-lake-id="u36485b5d" id="u36485b5d">主流语言,Open API</span></p></td><td data-lake-id="u38ae827f" id="u38ae827f"><p data-lake-id="u640e0cb5" id="u640e0cb5"><span data-lake-id="u0673ddda" id="u0673ddda">只支持 Spring 应用</span></p></td></tr><tr data-lake-id="u117f38c1" id="u117f38c1"><td data-lake-id="u2aa37925" id="u2aa37925"><p data-lake-id="uac7879d3" id="uac7879d3" style="text-align: left"><span data-lake-id="ubb128669" id="ubb128669">多环境</span></p></td><td data-lake-id="u62e0e8bb" id="u62e0e8bb"><p data-lake-id="u85240e03" id="u85240e03" style="text-align: left"><span data-lake-id="u80c82036" id="u80c82036">支持</span></p></td><td data-lake-id="u151946d0" id="u151946d0"><p data-lake-id="u2f4f8290" id="u2f4f8290" style="text-align: left"><span data-lake-id="uca6b7a7c" id="uca6b7a7c">支持</span></p></td><td data-lake-id="uf61b608f" id="uf61b608f"><p data-lake-id="u92af72dc" id="u92af72dc"><span data-lake-id="u985f48e3" id="u985f48e3">不支持</span></p></td></tr><tr data-lake-id="uaf766828" id="uaf766828"><td data-lake-id="u51d41dec" id="u51d41dec"><p data-lake-id="ua64c57e5" id="ua64c57e5" style="text-align: left"><span data-lake-id="uc37ba6cd" id="uc37ba6cd">监听查询</span></p></td><td data-lake-id="u8fbd46aa" id="u8fbd46aa"><p data-lake-id="uc4da69b9" id="uc4da69b9" style="text-align: left"><span data-lake-id="u6f8d8c22" id="u6f8d8c22">支持</span></p></td><td data-lake-id="uf84cd9a9" id="uf84cd9a9"><p data-lake-id="u5012340f" id="u5012340f" style="text-align: left"><span data-lake-id="u4efe2c4b" id="u4efe2c4b">支持</span></p></td><td data-lake-id="uc9229c9d" id="uc9229c9d"><p data-lake-id="u933a5a47" id="u933a5a47"><span data-lake-id="ub0ad76e8" id="ub0ad76e8">支持</span></p></td></tr></tbody></table>

Apollo 和 Nacos 提供了更多开箱即用的功能,更适合用来作为配置中心。

Nacos 使用起来比较简单,并且还可以直接用来做服务发现及管理。Apollo 只能用来做配置管理,使用相对复杂一些。

Apollo 在配置管理方面做的更加全面,就比如说虽然 Nacos 在 1.1.0 版本开始支持灰度配置,但 Nacos 的灰度配置功能实现的比较简单,Apollo 实现的灰度配置功能就相对更完善一些。不过,Nacos 提供的配置中心功能已经可以满足绝大部分项目的需求了。

一个完备配置中心需要具备哪些功能?

如果我们需要自己设计一个配置中心的话,需要考虑哪些东西呢?

简单说说我的看法:

  • 权限控制 :配置的修改、发布等操作需要严格的权限控制。

  • 日志记录 : 配置的修改、发布等操需要记录完整的日志,便于后期排查问题。

  • 配置推送 : 推送模式通常由两种:

  • 推 :实时性变更,配置更新后推送给应用。需要应用和配置中心保持长连接,复杂度高。

  • 拉 :实时性较差,应用隔一段时间手动拉取配置。

  • 推拉结合

  • 灰度发布 :支持配置只推给部分应用。

  • 易操作 : 提供 Web 界面方便配置修改和发布。

  • 版本跟踪 :所有的配置发布都有版本概念,从而可以方便的支持配置的回滚。

  • 支持配置回滚 : 我们一键回滚配置到指定的位置,这个需要和版本跟踪结合使用。

  • ......

以 Apollo 为例介绍配置中心的设计

Apollo 介绍

根据 Apollo 官方介绍:

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

服务端基于 Spring Boot 和 Spring Cloud 开发,打包后可以直接运行,不需要额外安装 Tomcat 等应用容器。

Java 客户端不依赖任何框架,能够运行于所有 Java 运行时环境,同时对 Spring/Spring Boot 环境也有较好的支持。

Apollo 特性:

  • 配置修改实时生效(热发布) (1s 即可接收到最新配置)
  • 灰度发布 (配置只推给部分应用)
  • 部署简单 (只依赖 MySQL)
  • 跨语言 (提供了 HTTP 接口,不限制编程语言)
  • ......

关于如何使用 Apollo 可以查看 Apollo 官方使用指南

相关阅读:

Apollo 架构解析

官方给出的 Apollo 基础模型非常简单:

  1. 用户通过 Apollo 配置中心修改/发布配置,
  2. Apollo 配置中心通知应用配置已经更改
  3. 应用访问 Apollo 配置中心获取最新的配置

官方给出的架构图如下:

  • Client 端(客户端,用于应用获取配置)流程 :Client 通过域名走 slb(软件负载均衡)访问 Meta Server,Meta Server 访问 Eureka 服务注册中心获取 Config Service 服务列表(IP+Port)。有了 IP+Port,我们就能访问 Config Service 暴露的服务比如通过 GET 请求获取配置的接口(/configs/{appId}/{clusterName}/{namespace:.+})即可获取配置。
  • Portal 端(UI 界面,用于可视化配置管理)流程 :Portal 端通过域名走 slb(软件负载均衡)访问 Meta Server,Meta Server 访问 Eureka 服务注册中心获取 Admin Service 服务列表(IP+Port)。有了 IP+Port,我们就能访问 Admin Service 暴露的服务比如通过 POST 请求访问发布配置的接口(/apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/releases)即可发布配置。

另外,杨波老师的微服务架构~携程 Apollo 配置中心架构剖析这篇文章对 Apollo 的架构做了简化,值得一看。

我会从上到下依次介绍架构图中涉及到的所有角色的作用。

Client

Apollo 官方提供的客户端,目前有 Java 和.Net 版本。非 Java 和.Net 应用可以通过调用 HTTP 接口来使用 Apollo。

Client 的作用主要就是提供一些开箱即用的方法方便应用获取以及实时更新配置。

比如你通过下面的几行代码就能获取到 someKey 对应的实时最新的配置值:

再比如你通过下面的代码就能监听配置变化:

Portal

Portal 实际就是一个帮助我们修改和发布配置的 UI 界面。

(Software) Load Balancer

为了实现 MetaServer 的高可用,MetaServer 通常以集群的形式部署。

Client/Portal 直接访问 (Software) Load Balancer ,然后,再由其进行负载均衡和流量转发。

Meta Server

为了实现跨语言使用,通常的做法就是暴露 HTTP 接口。为此,Apollo 引入了 MetaServer。

Meta Server 其实就是 Eureka 的 Proxy,作用就是将 Eureka 的服务发现接口以 HTTP 接口的形式暴露出来。 这样的话,我们通过 HTTP 请求就可以访问到 Config Service 和 AdminService。

通常情况下,我们都是建议基于 Meta Server 机制来实现 Config Service 的服务发现,这样可以实现 Config Service 的高可用。不过, 你也可以选择跳过 MetaServer,直接指定 Config Service 地址(apollo-client 0.11.0 及以上版本)。

Config Service

主要用于 Client 对配置的获取以及实时更新。

Admin Service

主要用于 Portal 对配置的更新。

参考

文章来源于自己总结和网络转载,内容如有任何问题,请大佬斧正!联系我