上一篇博客有讲到:【Apollo】(1)--- Apollo入门介绍篇html
这篇来写Apollo的核心架构设计git
Apollo总体架构图,已由做者宋顺已经给出:github
这幅图所描述的已经很清楚了。下面来具体解释下上面这张图。数据库
ConfigService
架构
提供配置的读取、推送等功能,服务对象是Apollo客户端(client)(最终目的就是把配置数据给到咱们本身的微服务对象)并发
Admin Service
负载均衡
提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)(简单理解成就是就是用来在配置中心管理界面来添加或者修改配置)运维
Client( 客户端)
分布式
Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能。微服务
域名访问 Meta Server 获取 Config Service 服务列表(IP+Port),然后直接经过IP+Port访问服务,同时在Client侧会作负载均衡、错误重试
Portal
提供Web界面供用户管理配置。
Portal经过域名访问 Meta Server 获取 Admin Service 服务列表(IP+Port),然后直接经过IP+Port访问服务,同时在Portal侧会作 负载均衡、错误重试
我的理解这四个模块
ConfigService 和 Client 的配合
从这里面能够看出咱们本身的微服务不是直接和ConfigService打交道的,而是跟Client打交道,Client才是真正和ConfigService打交道来获取最新配置信息。
Admin Service 和 Portal
这里分类两个模块就很好理解了,由于管理界面的实现有本身的一套代码,并且管理界面操做的一些权限等信息,只会跟它本身有关系,对于微服务来说,我只关心有没有配置
这条配置数据,而不会去关心在管理界面上什么用户可以添加配置信息。因此就有Portal对于了两个数据库,一个能够理解是它本身的,存放一些权限等信息,另外一部分是和
配置有关的,因此经过 Admin Service 存放在 configDB 中。
为了保证上面四个模块的高可用,因此这里须要三个辅助模块配合。
Eureka
用于服务发现和注册Config/AdminService注册实例并按期报心跳。
为了简化部署,咱们实际上会把Config Service、Eureka和Meta Server三个逻辑角色部署在同一个JVM进程中
官方也有解释为何咱们采用Eureka做为服务注册中心,而不是使用传统的zk、etcd呢?我大体总结了一下,有如下几方面的缘由:
1)它提供了完整的Service Registry和Service Discovery实现
首先是提供了完整的实现,而且也经受住了Netflix本身的生产环境考验,相对使用起来会比较省心。
2)和Spring Cloud无缝集成
咱们的项目自己就使用了Spring Cloud和Spring Boot,同时Spring Cloud还有一套很是完善的开源代码来整合Eureka,因此使用起来很是方便。另外,Eureka还支持在
咱们应用自身的容器中启动,也就是说咱们的应用启动完以后,既充当了Eureka的角色,同时也是服务的提供者。这样就极大的提升了服务的可用性。这一点是咱们选择
Eureka而不是zk、etcd等的主要缘由,为了提升配置中心的可用性和下降部署复杂度,咱们须要尽量地减小外部依赖。
3)Open Source
最后一点是开源,因为代码是开源的,因此很是便于咱们了解它的实现原理和排查问题。
MetaServer
Portal经过域名 访问 MetaServer 获取 AdminService 的地址列表。
Client经过域名访问MetaServer获取ConfigService的地址列表。
至关于一个Eureka Proxy 逻辑角色,和ConfigService住在一块儿部署。
NginxLB
和域名系统配合,协助Portal访问MetaServer获取AdminService地址列表。
和域名系统配合,协助Client访问MetaServer获取ConfigService地址列表。
和域名系统配合,协助用户访问Portal进行配置管理。
若是不考虑分布式微服务架构中的服务发现问题,Apollo的最简架构以下图(来源 杨波)所示:
要点
一、ConfigService是一个独立的微服务,服务于Client进行配置获取。
二、Client和ConfigService保持 长链接,经过一种拖拉结合(push & pull)的模式,实现配置实时更新的同时,保证配置更新不丢失。
三、AdminService是一个独立的微服务,服务于Portal进行配置管理。Portal经过调用AdminService进行配置管理和发布。
四、ConfigService和AdminService共享ConfigDB,ConfigDB中存放项目在某个环境的配置信息。ConfigService/AdminService/ConfigDB三者在每一个环境
(DEV/FAT/UAT/PRO)中都要部署一份。
五、Protal有一个独立的 PortalDB,存放用户权限、项目和配置的元数据信息。Protal只需部署一份
,它能够管理多套环境。
为了保证高可用,ConfigService和AdminService都是无状态以集群方式部署的,这个时候就存在一个服务发现问题:Client怎么找到ConfigService?Portal
怎么找到AdminService?为了解决这个问题,Apollo在其架构中引入了Eureka服务注册中心组件,实现微服务间的服务注册和发现,更新后的架构以下图所示:
要点
Config/AdminService启动后都会注册到Eureka服务注册中心,并按期发送保活心跳。
Eureka采用集群方式部署,使用分布式一致性协议保证每一个实例的状态最终一致。
咱们知道Eureka是自带服务发现的Java客户端的,若是Apollo只支持Java客户端接入,不支持其它语言客户端接入的话,那么Client和Portal只须要引入Eureka的Java
客户端,就能够实现服务发现功能。发现目标服务后,经过客户端软负载(SLB,例如Ribbon)就能够路由到目标服务实例。这是一个经典的微服务架构,基于Eureka实现
服务注册发现+客户端Ribbon配合实现软路由,以下图所示:
在携程,应用场景不只有Java,还有不少遗留的.Net应用。Apollo的做者也考虑到开源到社区之后,不少客户应用是非Java的。可是Eureka(包括Ribbon软负载)原生仅支持
Java客户端,若是要为多语言开发Eureka/Ribbon客户端,这个工做量很大也不可控。为此,Apollo的做者引入了MetaServer这个角色,它实际上是一个Eureka的Proxy,将
Eureka的服务发现接口以更简单明确的HTTP接口的形式暴露出来,方便Client/Protal经过简单的HTTPClient就能够查询到Config/AdminService的地址列表。获取到服务
实例地址列表以后,再以简单的客户端软负载(Client SLB)策略路由定位到目标实例,并发起调用。
如今还有一个问题,MetaServer自己也是无状态以集群方式部署的,那么Client/Protal该如何发现MetaServer呢?一种传统的作法是借助硬件或者软件负载均衡器,例如在
携程采用的是扩展后的NginxLB(也称Software Load Balancer),由运维为MetaServer集群配置一个域名,指向NginxLB集群,NginxLB再对MetaServer进行负载均衡和
流量转发。Client/Portal经过域名+NginxLB间接访问MetaServer集群。
引入MetaServer和NginxLB以后的架构以下图所示:
V4版本已是比较完成的Apollo架构全貌,如今还剩下最后一个环节:Portal也是无状态以集群方式部署的,用户如何发现和访问Portal?答案也是简单的传统作法,
用户经过域名+NginxLB间接访问MetaServer集群。
因此V5版本是包括用户端的最终的Apollo架构全貌,以下图所示:
它和个人架构是如何对应的?提示一下,宋顺的视角是一个从上往下的俯视视角,而个人是一个侧面视角。
发现的模块。
中的配置,这个是它的架构的一大亮点。。
上面设计这么复杂就是为了知足高可用,若是不考虑可用性,那么那么的v1图片就能够知足。咱们来下最终的架构图为何能知足高可用。
很明显这些模块任何一个挂掉,都能知足服务的能够用性。
别人骂我胖,我会生气,由于我内心认可了我胖。别人说我矮,我就会以为可笑,由于我内心知道我不可能矮。这就是咱们为何会对别人的攻击生气。 攻我盾者,乃我心里之矛(27)