配置中心原理和选型:Disconf、Apollo、Spring Cloud Config 和 Nacos
讲解4种常用的配置中心,对比其流程和原理,无论是面试还是技术选型,都非常有帮助。
大家好,我是楼仔!这是我写的第5篇关于“技术选型”相关的文章,前4篇分别为消息队列、注册中心、微服务网关、RPC框架,这篇配置中心应该是该系列的最后一篇,前后跨度近一年,应该是我跨度时间最长的一个系列了。
学完注册中心,再看配置中心这块,感觉简单很多,因为很多知识原理是相辅相成的,下面是文章目录:
配置中心基础
为什么要用配置中心?
配置实时生效:传统的静态配置方式要想修改某个配置只能修改之后重新发布应用,要实现动态性,可以选择使用数据库,通过定时轮询访问数据库来感知配置的变化。轮询频率低感知配置变化的延时就长,轮询频率高,感知配置变化的延时就短,但比较损耗性能,需要在实时性和性能之间做折中。配置中心专门针对这个业务场景,兼顾实时性和一致性来管理动态配置; 配置管理流程:配置的权限管控、灰度发布、版本管理、格式检验和安全配置等一系列的配置管理相关的特性,也是配置中心不可获取的一部分; 分布式场景:随着采用分布式的开发模式,项目之间的相互引用随着服务的不断增多,相互之间的调用复杂度成指数升高,每次投产或者上线新的项目时苦不堪言,需要引用配置中心治理。
配置中心支持功能
灰度发布:配置的灰度发布是配置中心比较重要的功能,当配置的变更影响比较大的时候,需要先在部分应用实例中验证配置的变更是否符合预期,然后再推送到所有应用实例。 权限管理:配置的变更和代码变更都是对应用运行逻辑的改变,重要的配置变更常常会带来核弹的效果,对于配置变更的权限管控和审计能力同样是配置中心重要的功能。 版本管理&回滚:当配置变更不符合预期的时候,需要根据配置的发布版本进行回滚。 配置格式校验:应用的配置数据存储在配置中心一般都会以一种配置格式存储,比如Properties、Json、Yaml等,如果配置格式错误,会导致客户端解析配置失败引起生产故障,配置中心对配置的格式校验能够有效防止人为错误操作的发生,是配置中心核心功能中的刚需。 监听查询:当排查问题或者进行统计的时候,需要知道一个配置被哪些应用实例使用到,以及一个实例使用到了哪些配置。 多环境:在实际生产中,配置中心常常需要涉及多环境或者多集群,业务在开发的时候可以将开发环境和生产环境分开,或者根据不同的业务线存在多个生产环境。如果各个环境之间的相互影响比较小(开发环境影响到生产环境稳定性),配置中心可以通过逻辑隔离的方式支持多环境。 多集群:当对稳定性要求比较高,不允许各个环境相互影响的时候,需要将多个环境通过多集群的方式进行物理隔离。
常用配置中心
写在前面
如果只要能作为分布式存储的服务都作为配置中心,那选择途径就太多了, 比如Zookeeper和ETCD,所以需要提前说明一下。
在文章 《注册中心原理和选型:Zookeeper、Eureka、Nacos、Consul和ETCD》 已经提到过,Zookeeper和ETCD可以存储数据,作为配置中心使用,比如我司的微服务网关,将配置发布到ETCD,供网关各模块调用,具体可以参考文章 《微服务网关:从对比到选型,由理论到实践》。
但是我们选择配置中心时,为什么不优先考虑Zookeeper和ETCD,因为以下两点原因:
没有方便的UI管理工具,且缺乏权限、审核、灰度发布、审核机制等; 最重要的是,Zookeeper和ETCD通常定义为服务注册中心,统一配置中心的事情交给专业的工具去解决。
大白话总结一下,就是专业的人干专业的事,他两很多功能没法支持。可能你会问,那你们公司为啥用ETCD作为配置中心呢?因为我们自己写了个后台,支持权限、灰度发布、版本控制等功能。
所以给大家介绍的配置中心,主要是以下4种,分别为 Disconf、Spring Cloud Config、Apollo 和 Nacos。
Apollo
GitHub:https://github.com/apolloconfig/apollo
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,具备规范的权限、流程治理等特性。
Apollo框架
Apollo的框架有点复杂,如果不考虑分布式微服务架构中的服务发现问题,Apollo的最简架构如下图所示:
这里面包含Apollo框架的4个核心模块:
ConfigService:提供配置获取接口,提供配置推送接口,服务于Apollo客户端。 AdminService:提供配置管理接口,提供配置修改发布接口,服务于管理界面Portal。 Client:为应用获取配置,支持实时更新,通过MetaServer获取ConfigService的服务列表,使用客户端软负载SLB方式调用ConfigService。 Portal:配置管理界面,通过MetaServer获取AdminService的服务列表,使用客户端软负载SLB方式调用AdminService。
调用流程:
ConfigService是一个独立的微服务,服务于Client进行配置获取。 Client和ConfigService保持长连接,通过一种拖拉结合(push & pull)的模式,实现配置实时更新的同时,保证配置更新不丢失。 AdminService是一个独立的微服务,服务于Portal进行配置管理。Portal通过调用AdminService进行配置管理和发布。 ConfigService和AdminService共享ConfigDB,ConfigDB中存放项目在某个环境的配置信息。ConfigService/AdminService/ConfigDB三者在每个环境(DEV/FAT/UAT/PRO)中都要部署一份。 Protal有一个独立的PortalDB,存放用户权限、项目和配置的元数据信息。Protal只需部署一份,它可以管理多套环境。
加上分布式微服务架构中的服务发现,真正的Apollo框架如下:
如果你了解RPC和注册中心,这幅图其实不难理解:
Eureka用于注册中心,AP原则,所以Config Service和Admin Service的机器列表注册到Eureka中; Client和Portal需要获取注册中心的机器列表,但是由于Eureka仅支持Java客户端,所以搞个Meta Server,将Eureka的服务发现接口以HTTP接口的形式暴露出来; 由于Meta Server是集群部署,需要搞个NginxLB去找Meta Server机器。
所以搞NginxLB + Meta Server,其实就是为了找Eureka中的机器列表配置,Client和Portal拿到这些机器配置,就可以发起调用了,最后就回到我们前面的简图,是不是So Easy!
我讲的已经够清楚了,如果还是不懂,就看这篇文章 《微服务架构~携程Apollo配置中心架构剖析》
Apollo特性
统一管理不同环境、不同集群的配置: Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。 同一份代码部署在不同的集群,可以有不同的配置,比如zk的地址等。 通过命名空间(namespace)可以很方便的支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖。 配置修改实时生效(热发布):用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。 版本发布管理 + 灰度发布 权限管理、发布审核、操作审计:应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。所有的操作都有审计日志,可以方便的追踪问题。 客户端配置信息监控:可以在界面上方便地看到配置在被哪些实例使用。 提供Java和.Net原生客户端: 提供了Java和.Net的原生客户端,方便应用集成。 支持Spring Placeholder、Annotation和Spring Boot的ConfigurationProperties,方便应用使用。 提供了Http接口,非Java和.Net应用也可以方便的使用。 提供开放平台API: Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。 Apollo出于通用性考虑,对配置的修改不会做过多限制,只要符合基本的格式就能够保存。 对于有些使用方,它们的配置可能会有比较复杂的格式,而且对输入的值也需要进行校验后方可保存,如检查数据库、用户名和密码是否匹配。对于这类应用,Apollo支持应用方通过开放接口在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制。
最后通过后台界面,直观感受一下:
Disconf
GitHub:https://github.com/knightliao/disconf
2014年7月百度开源的配置管理中心,同样具备配置的管理能力,不过目前已经不维护,最近的一次提交是两年前了。
Disconf框架
Disconf是一套完整的基于zookeeper的分布式配置统一解决方案,它通过disconf-web管理配置信息,然后将配置的key在Zookeeper上建立节点,disconf-client启动后拉取自身需要的配置信息并监听Zookeeper的节点。在web上更新配置信息会触发zk节点状态的变动,client可以实时感知到变化,然后从web上拉取最新配置信息。
这里想吐槽一下,Disconf官方文档的图画真的丑啊,关键是很不清晰,就不能好好维护一下么?
Disconf特点
支持配置(配置项+配置文件)的分布式化管理: 配置发布统一化 配置发布、更新统一化(云端存储、发布):配置存储在云端系统,用户统一在平台上进行发布、更新配置。 配置更新自动化:用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置。特殊地,如果用户为此配置定义了回调函数类,则此函数类会被自动调用。 配置异构系统管理: 异构包部署统一化:这里的异构系统是指一个系统部署多个实例时,由于配置不同,从而需要多个部署包(jar或war)的情况(下同)。使用Disconf后,异构系统的部署只需要一个部署包,不同实例的配置会自动分配。特别地,在业界大量使用部署虚拟化(如JPAAS系统,SAE,BAE)的情况下,同一个系统使用同一个部署包的情景会越来越多,Disconf可以很自然地与他天然契合。异构主备自动切换:如果一个异构系统存在主备机,主机发生挂机时,备机可以自动获取主机配置从而变成主机。 异构主备机Context共享工具:异构系统下,主备机切换时可能需要共享Context。可以使用Context共享工具来共享主备的Context。 注解式编程,极简的使用方式:我们追求的是极简的、用户编程体验良好的编程方式。通过简单的标注+极简单的代码撰写,即可完成复杂的配置分布式化。 需要Spring编程环境。 可以托管任何类型的配置文件。 提供界面良好Web管理功能,可以非常方便的查看配置被哪些实例使用了。
Spring Cloud Config
GitHub:https://github.com/spring-cloud/spring-cloud-config
2014年9月开源,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。
Spring Cloud Config 工作原理
应用架构图:
工作流程:
在部署环境之前,需要将相应的配置信息推送到配置仓库; 配置服务器启动之后,将配置信息拉取并同步至本地仓库; 配置服务器对外提供REST接口,其他所有的配置客户端启动时根据spring.cloud.config配置的{application}/{profile}/{label}信息去配置服务器拉取相应的配置。配置仓库支持多样的源,如Git、SVN、jdbc数据库和本地文件系统等。 其他应用启动,从配置服务器拉取配置。(配置中心还支持动态刷新配置信息,不需要重启应用,通过spring-cloud-config-monitor监控模块,其中包含了/monitor刷新API,webhook调用该端点API,达到动态刷新的效果。)
Spring Cloud Config 特点
提供配置的服务端和客户端支持; 集中式管理分布式环境下的应用配置; 基于 Spring 环境,可以无缝与Spring应用集成; 可用于任何语言开发的程序,为其管理与提供配置信息; 默认实现基于git仓库,可以进行版本管理。
Nacos
Nacos官网:https://nacos.io/zh-cn/docs/what-is-nacos.html
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
Nacos 主要特点
服务发现和服务健康监测:
Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用原生SDK、OpenAPI、或一个独立的Agent TODO注册 Service 后,服务消费者可以使用DNS TODO 或HTTP&API查找和发现服务。 Nacos 提供对服务的实时的健康检查,阻止向不健康的主机或服务实例发送请求。Nacos 支持传输层 (PING 或 TCP)和应用层 (如 HTTP、MySQL、用户自定义)的健康检查。对于复杂的云环境和网络拓扑环境中(如 VPC、边缘网络等)服务的健康检查,Nacos 提供了 agent 上报模式和服务端主动检测2种健康检查模式。Nacos 还提供了统一的健康检查仪表盘,帮助您根据健康状态管理服务的可用性及流量。
动态配置服务:
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。 动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。 配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。 Nacos 提供了一个简洁易用的UI (控制台样例 Demo) 帮助您管理所有的服务和应用的配置。Nacos 还提供包括配置版本跟踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
动态 DNS 服务:
动态 DNS 服务支持权重路由,让您更容易地实现中间层负载均衡、更灵活的路由策略、流量控制以及数据中心内网的简单DNS解析服务。动态DNS服务还能让您更容易地实现以 DNS 协议为基础的服务发现,以帮助您消除耦合到厂商私有服务发现 API 上的风险。 Nacos 提供了一些简单的 DNS APIs TODO 帮助您管理服务的关联域名和可用的 IP:PORT 列表。
小节一下:
Nacos是阿里开源的,支持基于 DNS 和基于 RPC 的服务发现。 Nacos的注册中心支持CP也支持AP,对他来说只是一个命令的切换,随你玩,还支持各种注册中心迁移到Nacos,反正一句话,只要你想要的他就有。 Nacos除了服务的注册发现之外,还支持动态配置服务,一句话概括就是Nacos = Spring Cloud注册中心 + Spring Cloud配置中心。
配置中心对比和选型
由于 Disconf 不再维护,下面对比一下 Spring Cloud Config、Apollo 和 Nacos。
配置中心对比
灰度发布: Spring Cloud Config支持通过/bus/refresh端点的destination参数来指定要更新配置的机器,不过整个流程不够自动化和体系化。 Apollo可以直接在控制台上点灰度发布指定发布机器的IP,接着再全量发布,做得比较体系化。Nacos目前发布到0.9版本,还不支持灰度发布。 权限管理: Spring Cloud Config依赖Git的权限管理能力,开源的GitHub权限控制可以分为Admin、Write和Read权限,权限管理比较完善。 Apollo通过项目的维度来对配置进行权限管理,一个项目的owner可以授权给其他用户配置的修改发布权限。 Nacos目前看还不具备权限管理能力。 版本管理&回滚: Spring Cloud Config、Apollo和Nacos都具备配置的版本管理和回滚能力,可以在控制台上查看配置的变更情况或进行回滚操作。 Spring Cloud Config通过Git来做版本管理,更方便些。 配置格式校验: Spring Cloud Config使用Git,目前还不支持格式检验,格式的正确性依赖研发人员自己。 Apollo和Nacos都会对配置格式的正确性进行检验,可以有效防止人为错误。 监听查询: Spring Cloud Config使用Spring Cloud Bus推送配置变更,Spring Cloud Bus兼容 RabbitMQ、Kafka等,支持查询订阅Topic和Consumer的订阅关系。 Apollo可以通过灰度实例列表查看监听配置的实例列表,但实例监听的配置(Apollo称为命名空间)目前还没有展示出来。 Nacos可以查看监听配置的实例,也可以查看实例监听的配置情况。 基本上,这三个产品都具备监听查询能力,在我们自己的使用过程中,Nacos使用起来相对简单,易用性相对更好些。 多环境: Spring Cloud Config支持Profile的方式隔离多个环境,通过在Git上配置多个Profile的配置文件,客户端启动时指定Profile就可以访问对应的配置文件。 Apollo也支持多环境,在控制台创建配置的时候就要指定配置所在的环境,客户端在启动的时候指定JVM参数ENV来访问对应环境的配置文件。 Nacos通过命名空间来支持多环境,每个命名空间的配置相互隔离,客户端指定想要访问的命名空间就可以达到逻辑隔离的作用。 多集群: Spring Cloud Config可以通过搭建多套Config Server,Git使用同一个Git的多个仓库,来实现物理隔离。 Apollo可以搭建多套集群,Apollo的控制台和数据更新推送服务分开部署,控制台部署一套就可以管控多个集群。 Nacos控制台和后端配置服务是部署在一起的,可以通过不同的域名切换来支持多集群。 配置实时推送: Nacos和Apollo配置推送都是基于HTTP长轮询,客户端和配置中心建立HTTP长联接,当配置变更的的时候,配置中心把配置推送到客户端。 Spring Cloud Config原生不支持配置的实时推送,需要依赖Git的WebHook、Spring Cloud Bus和客户端/bus/refresh端点。 Nacos和Apollo在配置实时推送链路上是比较简单高效的,Spring Cloud Config的配置推送引入Spring Cloud Bus,链路较长,比较复杂。 多语言支持: Spring Cloud服务于Java生态,一开始只是针对Java微服务应用,对于非Java应用的微服务调用,可以使用Sidecar提供了HTTP API,但动态配置方面还不能很好的支持。 Apollo已经支持了多种语言,并且提供了open API。其他不支持的语言,Apollo的接入成本相对较低。 Nacos支持主流的语言,例如Java、Go、Python、Nodejs、PHP等,也提供了open API。 性能对比: Nacos的读写性能最高,Apollo次之,Spring Cloud Config的依赖Git场景不适合开放的大规模自动化运维API。
配置中心选型
总的来说:
Apollo和Nacos相对于Spring Cloud Config的生态支持更广,在配置管理流程上做的更好。 Apollo相对于Nacos在配置管理做的更加全面,不过使用起来也要麻烦一些。 Apollo容器化较困难,Nacos有官网的镜像可以直接部署,总体来说,Nacos比Apollo更符合KISS原则。 Nacos使用起来相对比较简洁,在对性能要求比较高的大规模场景更适合。
此外,Nacos除了提供配置中心的功能,还提供了动态服务发现、服务共享与管理的功能,降低了服务化改造过程中的难度。
但对于一个开源项目的选型,除了以上这几个方面,项目上的人力投入(迭代进度、文档的完整性)、社区的活跃度(issue的数量和解决速度、Contributor数量、社群的交流频次等)、社区的规范程度(免责说明、安全性说明等),这些可能才是用户更关注的内容。
更多对比选型内容,请参考文章 《阿里面试这样问:Nacos、Apollo、Config配置中心如何选型?这10个维度告诉你!》,文中很多知识点也是来自该文章。
尽信书则不如无书,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激。
往期精选: