为什么要有分布式配置中心?
微服务架构下,服务的数量视项目的规模大小而定,但数量肯定最少有十几二十个,这些微服务有时候共用一些配置,修改一个配置,这诸多服务都要跟着一起改。任务繁多,而且容易出错。
分布式分配置中心将多个服务的配置集中在一处进行管理,统一修改,实时生效,节约时间的同时还降低出错率。
这篇文章和大家一起探讨下一款配置管理软件:Apollo
。
Apollo简介
关于Apollo的简介,人家自己官网的介绍就是最权威的:
Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。
安装部署指南
Apollo的官方文档写的非常棒,关于安装部署,可以直接参考:
Apollo基础模型
该图描述了Apollo的基础模型,其含义:
- 用户在配置中心对配置项进行修改并发布;
- 配置中心通知Apollo客户端有配置更新;
- Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用
Apollo核心模块
先来看一张Apollo官方给出的架构图:
有点微服务架构知识就差不多能从这个图上提取出几个核心模块:
- Config Service
- Admin Service
- Eureka集群
- Meta Server
- Client
- Portal
把这几个模块摘出来之后,我们来简单分析一下其架构模型:
Eureka
是微服务注册中心,Config Service
和Admin Service
向Eureka
注册服务Client
通过Meta Server
从Eureka
获取Config Service
服务列表Portal
通过Meta Server
从注册中心获取Admin Service
服务列表Client
和Portal
侧都会通过Software Load Balancer
做负载均衡
上面简单分析是从这个架构图出发做的简要分析,下面我们再来看一下,各个模块的职能是什么。
Config Service
Config Service
的服务对象为Apoll客户端
,Apollo客户端从Config Service提供的接口获取需要的配置项;
当配置项更新后,Config Service负责推送消息通知给Apollo客户端。
TIP:
- Config Service推送消息采用异步的方式(Spring DeferredResult),从而大大增加长连接数量
- 目前使用的内置tomcat默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
Admin Service
Admin Service
提供了对配置进行管理的接口,包括 修改、发布 等接口,其服务对象是Portal
。
Meta Server
Meta Server相当于一个Eureka Proxy:
Portal
通过域名访问Meta Server
获取Admin Service
的地址列表Client
通过域名访问Meta Server
获取Config Service
的地址列表
Meta Server
和 Config Service
部署在一个JVM中。
Eureka
Eureka
是 Spring Cloud
的重要组件,负责服务的注册发现。
Config Service
和 Admin Service
会向 Eureka
注册服务,并保持心跳。
Eureka
也是和 Config Service
部署在同一个JVM中的。
Portal
通过 Portal
可以对配置进行可视化管理。
- 通过Meta Server获取Admin Service服务列表(IP+Port),通过
IP+Port
访问服务 - 在Portal侧做load balance、错误重试
Client
Client
是Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能。
- 通过Meta Server获取Config Service服务列表(IP+Port),通过IP+Port访问服务
- 在Client侧做load balance、错误重试
Apollo核心概念
应用 application
应用就是为服务项目,Apollo客户端在运行时需要知道每一个应用的标识,
每个应用都需要有唯一的身份标识 — appId
,指定 appId
的方式有多种,SpringBoot项目建议直接配置在application.yml
中,跟着项目走。
环境 environment
环境就是平常所说的开发、测试、预发布、生产等环境。Apollo客户端不仅需要知道应用的的身份标识,还需要知道应用所处的环境,因为不同的环境其配置是不一样的。
分布式部署需要事先确定部署的环境以及部署方式。
指定项目的环境也有多种方式,环境默认是通过读取机器上的配置(server.properties中的env属性)指定的,
同时还支持通过Java System Property来指定。
Apollo目前支持以下环境:
- DEV 开发环境
- FAT 测试环境,相当于alpha环境(功能测试)
- UAT 集成环境,相当于beta环境(回归测试)
- PRO 生产环境
当然,你也可以通过源码
com.ctrip.framework.apollo.core.enums.Env
和 com.ctrip.framework.apollo.core.enums.EnvUtils
来自定义环境。
集群 cluster
一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
对不同的cluster,同一个配置可以有不一样的值,如zookeeper地址。
集群默认是通过读取机器上的配置(server.properties中的idc属性)指定的,不过也支持运行时通过Java System Property指定。
命名空间 namespace
- 一个应用下不同配置的分组。可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
- 应用可以直接读取到公共组件的配置namespace,如DAL,RPC等
- 应用也可以通过继承公共组件的配置namespace来对公共组件的配置做调整,如DAL的初始数据库连接数
实战
Apollo配置中心搭建
主机规划
我用三台CentOS虚拟机搭建了一个简化版的Apollo配置中心:
主机名称 | IP地址 | 部署项目 | 备注 |
---|---|---|---|
apollo-node-111 | 192.168.242.111 | MySQL、Admin Service(DEV)、Config Service(DEV) | |
apollo-node-112 | 192.168.242.112 | Portal、Admin Service、Config Service | 没有对Portal做高可用 |
apollo-node-113 | 192.168.242.113 | Admin Service、Config Service |
部署
-
在
apollo-node-111
机器上准备工作
根据前文所述的主机规划,需要在
apollo-node-111
机器部署数据库和DEV环境。修改相应的脚本:
修改
admin service
的配置文件:vim /usr/local/apollo/apollo-adminservice/config/application-github.properties # 文件内容 # DataSource spring.datasource.url = jdbc:mysql://192.168.242.111:3306/ApolloConfigDBTest?characterEncoding=utf8 spring.datasource.username = root spring.datasource.password = 123456 复制代码
修改 config service 的配置文件:
vim /usr/local/apollo/apollo-configservice/config/application-github.properties # 文件内容 # DataSource spring.datasource.url = jdbc:mysql://192.168.242.111:3306/ApolloConfigDBTest?characterEncoding=utf8 spring.datasource.username = root spring.datasource.password = 123456 复制代码
-
导入ApolloPortalDB和ApolloConfigDB数据库,并复制一个ApolloConfigDBTest库作为DEV环境的数据库(自行修改sql脚本)。
# 进入到MySQL客户端 mysql> source /usr/local/apollo/sql/apolloportaldb.sql; mysql> source /usr/local/apollo/sql/apolloconfigdb.sql; mysql> source /usr/local/apollo/sql/apolloconfigdbtest.sql; 复制代码
-
启动
Config Service
,执行脚本:/usr/local/apollo/apollo-configservice/scripts/startup.sh 复制代码
-
启动
Admin Service
,执行如下脚本:/usr/local/apollo/apollo-adminservice/scripts/startup.sh 复制代码
查看启动的服务:
[root@apollo-node-111 ~]# jps 76338 Jps 75865 apollo-configservice.jar 76174 apollo-adminservice.jar 复制代码
服务器
apollo-node-111
启动了config
和admin
两个服务。 -
-
在
apollo-node-112
上修改
admin service
、config service
、portal
的配置文件,指定数据库地址均为192.168.242.111
,配置方式同第1步。另外,
Portal
还有个apollo-env.properties
配置文件,修改其内容如下:dev.meta=http://192.168.242.111:8080 pro.meta=http://192.168.242.112:8080,http://192.168.242.113:8080 复制代码
按照主机规划,在改机器上要启动三个服务:
# 启动config service /usr/local/apollo/apollo-configservice/scripts/startup.sh # 启动admin service /usr/local/apollo/apollo-adminservice/scripts/startup.sh # 启动portal /usr/local/apollo/apollo-portal/scripts/startup.sh 复制代码
-
在
apollo-node-113
上修改
admin service
、**config service
**的配置文件,指定数据库地址均为192.168.242.111
,配置方式同第1步。只启动
admin
和config
两个服务,此处略。
三台机器部署完成,输入 portal 地址:http://192.168.242.112:8070/
默认用户名/密码:apollo/admin。
实战
登录到 Apollo Portal
后,添加项目、环境以及namespace可参考官方文档,这里不再赘述。
下面开始使用 配置
。
添加配置:
发布一下:
下面开始使用配置,新建一个SpringBoot项目,引入Apollo Maven依赖:
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.8.0</version>
</dependency>
复制代码
配置文件 application.properties
:
# 应用名称
spring.application.name=apollo-demo
# 应用服务 WEB 访问端口
server.port=8080
app.id=apollo-demo
apollo.meta=http://192.168.242.112:8080,http://192.168.242.113:8080
apollo.bootstrap.enabled=true
apollo.bootstrap.namespace=common
复制代码
写一个测试Controller,使用注解方式获取配置,或者监听配置的更新:
@RestController
@RequestMapping("/test")
public class TestController {
@ApolloConfig
private Config config;
@GetMapping("/config/expiredMinutes")
public String getExpiredMinutes() {
return config.getProperty("expiredMinutes", "30");
}
@ApolloConfigChangeListener
private void configOnChange(ConfigChangeEvent changeEvent) {
if (changeEvent.isChanged("expiredMinutes")) {
System.out.println("expiredMinutes发生了更新:" + config.getProperty("expiredMinutes", "30"));
}
}
}
复制代码
项目启动后,访问/config/expiredMinutes
得到配置项的值:
现在来更新一下expiredMinutes
:
至此,我们就实现了Apollo配置中心的使用。
首发公众号 行百里er ,欢迎老铁们关注阅读指正。GitHub gitee.com/xblzer/Java…