Apollo分布式配置中心
1.概述
1.1定义
Apollo,称阿波罗,是携程研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。它支持4个维度管理Key-Value格式的配置。
1.2特性
1)统一管理不同环境、不同集群的配置
Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。同一份代码部署在不同的集群,可以有不同的配置。通过命名空间(namespace)可以很方便的支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
2)配置修改实时生效(热发布)
用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
3)版本发布管理
所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
4)灰度发布
点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
5)权限管理、发布审核、操作审计
应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。另外所有的操作都有审计日志,可以方便的追踪问题
1.3执行流程
执行流程图如下:
流程说明:
A:用户在配置中心发布或修改配置
B:Apollo客户端定时拉取配置中心的配置。若配置中心发生故障,则apollo客户端会从本地缓存中获取配置信息
C:应用程序从客户端获取配置信息并更新通知
D:除了apollo客户端定时从拉取配置中心拉取之外,配置中心还可以实时的推送配置更新信息到apollo客户端,那么客户端再把配置给应用程序
2.安装及部署
可参考官方指南https://github.com/ctripcorp/apollo/wiki/%E5%88%86%E5%B8%83%E5%BC%8F%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97#,本操作均按照指南进行说明的。
2.1环境要求
1)服务端基于Spring Boot框架,一般放在Centos7上
2)JDK版本需在1.8+
3)MySQL版本需在5.6.5+
2.2在Linux手动部署服务端
2.2.1创建数据库
Apollo服务端共需要两个数据库:ApolloPortalDB
和ApolloConfigDB
。ApolloPortalDB只需要在生产环境部署一个即可,而ApolloConfigDB需要在每个环境部署一套。
1)创建ApolloPortalDB数据库:复制apolloportaldb.sql后执行。
2)创建ApolloConfigDB数据库:复制apolloconfigdb.sql后执行。
2.2.2下载安装包
1)直接从GitHub Release下载即可。
这里以1.8.1版本为例,需要分别下载apollo-configservice-1.8.1-github.zip、apollo-adminservice-1.8.1-github.zip和apollo-portal-1.8.1-github.zip。如下图:
2)修改数据库配置信息
下载后在本地解压,然后分别打开三个这文件夹下的config/application-github.properties
文件,修改数据库的连接信息。下面以一个为例说明:
# DataSource spring.datasource.url = jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 spring.datasource.username = admin spring.datasource.password = 1234
需要修改数据库的地址,用户名和密码。需要注意的是在用户名和密码未部不能有空格!这里的MySQL使用的是8.0+版本的,使用docker容器启动的,专门创建了一个用户,用于外部的访问。
3)修改portal的环境配置
这里以默认的dev环境进行说明,若需要添加其他的环境,可参考后续章节。
打开apollo-portal-1.8.1-github/config/apollo-env.properties
文件,修改dev.meta的值
dev.meta=http://localhost:8080
2.2.3启动服务
1)把上一步修改好后的三个文件夹全部上传到虚拟机中。
2)部署apollo-configservice
cd apollo-configservice-1.8.1-github/scripts
./startup.sh
启动需要几分钟,看到下图的执行结果说明启动成功!后面的两个服务类同。
停止服务
./shutdown.sh
3)部署apollo-adminservice
cd apollo-adminservice-1.8.1-github/scripts
./startup.sh
4)部署apollo-portal
cd apollo-portal-1.8.1-github/scripts
./startup.sh
都启动后访问http://192.168.86.128:8070/,这里的ip是虚拟机的ip。看到apollo的登录页面,说明服务均部署成功。
5)登录管理页面
默认的用户名是apollo,密码是admin,即可登录进入首页,第一次进来可能会提示下图的错误信息,这时需要点击左下角的补缺环境就可以正常使用了。
正常情况下是下图:
用户名和密码存储在apolloportaldb数据库的Users表中,可修改。
2.3在Linux使用Docker部署服务端
Apollo1.7.0及以上的版本才能使用Docker部署,这里以1.8.1版本为例。数据库在此略,请参考上一小节的创建数据库操作说明。
2.3.1部署apollo-configservice
1)拉取镜像
docker pull apolloconfig/apollo-configservice:1.8.1
2)启动镜像
首次启动时需要指定一些参数,后续只需要启动此容器即可。每行尾部的反斜杠“\”表示换行。
docker run -p 8080:8080 \ -e SPRING_DATASOURCE_URL="jdbc:mysql://192.168.86.128:3306/ApolloConfigDB?characterEncoding=utf8" \ -e SPRING_DATASOURCE_USERNAME=admin -e SPRING_DATASOURCE_PASSWORD=1234 \ -e EUREKA_INSTANCE_IP_ADDRESS=192.168.86.128 -d -v /tmp/logs:/opt/logs --name apollo-configservice apolloconfig/apollo-configservice:1.8.1
参数说明:
SPRING_DATASOURCE_URL: 环境ApolloConfigDB的数据库地址 SPRING_DATASOURCE_USERNAME: 环境ApolloConfigDB数据库用户名 SPRING_DATASOURCE_PASSWORD: 环境ApolloConfigDB数据库密码 EUREKA_INSTANCE_IP_ADDRESS:eureka的地址,不能再使用localhost
由于mysql也使用的是docker容器,演示示例中客户端和服务端不在同一台机器上,故这里数据的连接必须使用ip进行访问,不能使用localhost,否则服务无法启动成功。若在正式环境中,服务端和客户端在同一机器上,那么就不需要设置eureka地址。后续使用docker部署同。
3)修改eureka的地址
由于使用的是容器,故需要把eureka的地址中localhost改为ip:
use ApolloConfigDB; update ServerConfig t set t.Value = 'http://192.168.86.128:8080/eureka/' where t.Key = 'eureka.service.url'
这里不改的话,config服务启动时会报异常。
12.3.2部署apollo-adminservice
1)拉取镜像
docker pull apolloconfig/apollo-adminservice:1.8.1
2)启动镜像
首次启动时需要指定一些参数,后续只需要启动此容器即可。每行尾部的反斜杠“\”表示换行。
docker run -p 8090:8090 \ -e SPRING_DATASOURCE_URL="jdbc:mysql://192.168.86.128:3306/ApolloConfigDB?characterEncoding=utf8" \ -e SPRING_DATASOURCE_USERNAME=admin -e SPRING_DATASOURCE_PASSWORD=1234 \ -d -v /tmp/logs:/opt/logs --name apollo-adminservice apolloconfig/apollo-adminservice:1.8.1
参数说明:
SPRING_DATASOURCE_URL: 环境ApolloConfigDB的数据库地址 SPRING_DATASOURCE_USERNAME: 环境ApolloConfigDB数据库用户名 SPRING_DATASOURCE_PASSWORD: 环境ApolloConfigDB数据库密码
2.3.3部署apollo-portal
1)拉取镜像
docker pull apolloconfig/apollo-portal:1.8.1
2)启动镜像
首次启动时需要指定一些参数,后续只需要启动此容器即可。每行尾部的反斜杠“\”表示换行。
docker run -p 8070:8070 \ -e SPRING_DATASOURCE_URL="jdbc:mysql://192.168.86.128:3306/ApolloPortalDB?characterEncoding=utf8" \ -e SPRING_DATASOURCE_USERNAME=admin -e SPRING_DATASOURCE_PASSWORD=1234\ -e APOLLO_PORTAL_ENVS=dev \ -e DEV_META=http://192.168.86.128:8080 \ -d -v /tmp/logs:/opt/logs --name apollo-portal apolloconfig/apollo-portal:1.8.1
参数说明:
SPRING_DATASOURCE_URL: 环境ApolloPortalDB数据库地址 SPRING_DATASOURCE_USERNAME: 环境ApolloPortalDB数据库用户名 SPRING_DATASOURCE_PASSWORD: 环境ApolloPortalDB数据库密码 APOLLO_PORTAL_ENVS(可选): 对应ApolloPortalDB中的apollo.portal.envs配置项,如果没有在数据库中配置的话,可以通过此环境参数配置 DEV_META/PRO_META(可选): 配置对应环境的Meta Service地址,以${ENV}_META命名,需要注意的是如果配置了ApolloPortalDB中的apollo.portal.meta.servers配置,则以apollo.portal.meta.servers中的配置为准
这里只配置了dev环境。若配置多环境,启动时再添加参数即可,下列代码标红的地方便是添加pro后的样子:
docker run -p 8070:8070 \ -e SPRING_DATASOURCE_URL="jdbc:mysql://192.168.86.128:3306/ApolloPortalDB?characterEncoding=utf8" \ -e SPRING_DATASOURCE_USERNAME=admin -e SPRING_DATASOURCE_PASSWORD=1234\ -e APOLLO_PORTAL_ENVS=dev,pro \ -e DEV_META=http://localhost:8080 -e PRO_META=http://ip:8080 \ -d -v /tmp/logs:/opt/logs --name apollo-portal apolloconfig/apollo-portal:1.8.1
2.4在Linux使用Docker-Compose部署服务端
在上一小节使用的docker命令方式部署服务端,本小节使用Docker-Compose进行部署,故默认已安装docker-compose镜像,若未安装,请参考https://www.cnblogs.com/zys2019/p/13292619.html#_label4。
1)数据库请参数2.2小节的创建数据库操作。
2)修改数据库中eureka的地址
use ApolloConfigDB; update ServerConfig t set t.Value = 'http://192.168.86.128:8080/eureka/' where t.Key = 'eureka.service.url'
3)在opt目录下新建apollo目录,在apollo目录新建.env文件,内容如下:
DATASOURCE_URL_CONFIG=jdbc:mysql://192.168.86.128:3306/ApolloConfigDB?characterEncoding=utf8 DATASOURCE_URL_PORTAL=jdbc:mysql://192.168.86.128:3306/ApolloPortalDB?characterEncoding=utf8 DATASOURCE_USERNAME=admin DATASOURCE_PASSWORD=1234 APOLLO_PORTAL_ENVS=dev DEV_META=http://192.168.86.128:8080 EUREKA_INSTANCE_IP_ADDRESS=192.168.86.128
此文件的作用是定义公共的变量,在docker-compose.yml中直接获取即可。
4)在apollo目录下新建docker-compose.yml文件,内容如下:
version: '3.7' services: apollo-configservice: container_name: apollo-configservice restart: always image: apolloconfig/apollo-configservice:1.8.1 ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} EUREKA_INSTANCE_IP_ADDRESS: ${EUREKA_INSTANCE_IP_ADDRESS} volumes: - /tmp/logs:/opt/logs apollo-adminservice: container_name: apollo-adminservice depends_on: - apollo-configservice restart: always image: apolloconfig/apollo-adminservice:1.8.1 expose: - '8090' environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} volumes: - /tmp/logs:/opt/logs apollo-portal: container_name: apollo-portal depends_on: - apollo-adminservice restart: always image: apolloconfig/apollo-portal:1.8.1 ports: - 8070:8070 environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_PORTAL} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} APOLLO_PORTAL_ENVS: ${APOLLO_PORTAL_ENVS} DEV_META: ${DEV_META} volumes: - /tmp/logs:/opt/logs
完成后在当前位置启动docker-compose即可,命令是:
docker-compose up -d
2.5在配置中心配置相关信息
服务端部署完成后,访问http://192.168.86.128:8070并登录进入首页。下面的操作均以进入首页后说明。
1)创建项目
点击首页的创建项目,填写项目的相关信息
部门:选择应用所在的部门 应用AppId:用来标识应用身份的唯一id,格式为string 应用名称:应用名,仅用于界面展示。 应用负责人:选择的人默认会成为该项目的管理员,具备项目权限管理、集群创建、Namespace创建等权限。
2)添加配置项
点击页面的新增配置按钮,配置需要管理的 application.properties 中的属性,这是第一步。
在弹框中输入key和value,这里以count=20为例,点击提交
提交后在页面会显示出来
3)发布配置
选择发布按钮,发布配置,这是第二步。在发布的弹框中选择发布按钮即可
发布后界面就会显示已发布
3.apollo客户端的安装
经过配置中心的配置,就可以使用SpringBoot来整合apollo了。源码:https://github.com/zhongyushi-git/springboot-apollo-demo.git
1)新建一个SpringBoot的项目。新建时选择web的依赖
2)导入apollo的依赖
<dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</artifactId> <version>1.3.0</version> </dependency>
3)在配置文件application.properties配置apollo的相关信息
#阿波罗配置 app.id = apollo-application apollo.meta=http://192.168.86.128:8080 apollo.bootstrap.enabled = true apollo.bootstrap.eagerLoad.enabled=true
说明:
app.id:AppId是应用的身份信息,是配置中心获取配置的一个重要信息。这个必须和配置中心保持一致 apollo.meta:指定config服务地址 apollo.bootstrap.enabled:在应用启动阶段,向Spring容器注入被托管的application.properties文件的配置信息。 apollo.bootstrap.eagerLoad.enabled:将Apollo配置加载提到初始化日志系统之前。
4)在启动类上添加注解@EnableApolloConfig
5)编写一个controller接口,读取配置文件的信息
package com.zxh.springbootapollodemo.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/test") public class TestController { @Value("${count}") private Integer count; @GetMapping("/get") public String test() { return "count的值:" + count; } }
6)启动项目,访问http://localhost:8080/test/get,返回正确的信息
7)在配置中心修改count的值,将其改为666并发布
8)看到控制台打印了日志,更新了配置的信息,再访问get接口,返回的也是最新的值
当然有时无法及时的更新,可能是网络原因,也可能是时间问题,发布后等待一分钟再进行测试。
4.使用Docker-Compose部署多环境
上述讲的都是单个环境,一般情况下会部署多环境,下面在同一台linux机器上部署dev和pro环境。
4.1创建数据库
参考2.2小节的创建数据库操作,分别创建如下图数据库:
其中ApolloPortalDB只需要创建一个,而ApolloConfigDB需要对每个环境单独创建一个。创建完成后修改eureka的服务地址:
use ApolloConfigDB_DEV; update ServerConfig t set t.Value = 'http://192.168.86.128:8080/eureka/' where t.Key = 'eureka.service.url'; use ApolloConfigDB_PRO; update ServerConfig t set t.Value = 'http://192.168.86.128:8081/eureka/' where t.Key = 'eureka.service.url';
4.2创建.env文件
在/opt目录下新建目录,名字为apollo_profile,在apollo_profile目录下新建.env文件,内容如下:
DATASOURCE_URL_CONFIG_DEV=jdbc:mysql://192.168.86.128:3306/ApolloConfigDB_DEV?characterEncoding=utf8 DATASOURCE_URL_CONFIG_PRO=jdbc:mysql://192.168.86.128:3306/ApolloConfigDB_PRO?characterEncoding=utf8 DATASOURCE_URL_PORTAL=jdbc:mysql://192.168.86.128:3306/ApolloPortalDB?characterEncoding=utf8 DATASOURCE_USERNAME=admin DATASOURCE_PASSWORD=1234 APOLLO_PORTAL_ENVS=dev,pro DEV_META=http://192.168.86.128:8080 PRO_META=http://192.168.86.128:8081 EUREKA_INSTANCE_IP_ADDRESS=192.168.86.128
这里面设置了一些公共的变量,方便维护。
4.3创建docker-compose.yml文件
在apollo_profile目录下新建docker-compose.yml文件,内容如下:
version: '3.7' services: apollo-configservice-dev: container_name: apollo-configservice-dev restart: always image: apolloconfig/apollo-configservice:1.8.1 ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG_DEV} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} EUREKA_INSTANCE_IP_ADDRESS: ${EUREKA_INSTANCE_IP_ADDRESS} volumes: - /tmp/logs:/opt/logs apollo-adminservice-dev: container_name: apollo-adminservice-dev depends_on: - apollo-configservice-dev restart: always image: apolloconfig/apollo-adminservice:1.8.1 expose: - '8090' environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG_DEV} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} volumes: - /tmp/logs:/opt/logs apollo-configservice-pro: container_name: apollo-configservice-pro restart: always image: apolloconfig/apollo-configservice:1.8.1 ports: - 8081:8081 environment: #修改容器启动的端口号 SERVER_PORT: '8081' SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG_PRO} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} EUREKA_INSTANCE_IP_ADDRESS: ${EUREKA_INSTANCE_IP_ADDRESS} volumes: - /tmp/logs:/opt/logs apollo-adminservice-pro: container_name: apollo-adminservice-pro depends_on: - apollo-configservice-pro restart: always image: apolloconfig/apollo-adminservice:1.8.1 expose: - '8090' environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_CONFIG_PRO} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} volumes: - /tmp/logs:/opt/logs apollo-portal: container_name: apollo-portal depends_on: - apollo-adminservice-dev - apollo-adminservice-pro restart: always image: apolloconfig/apollo-portal:1.8.1 ports: - 8070:8070 environment: SPRING_DATASOURCE_URL: ${DATASOURCE_URL_PORTAL} SPRING_DATASOURCE_USERNAME: ${DATASOURCE_USERNAME} SPRING_DATASOURCE_PASSWORD: ${DATASOURCE_PASSWORD} APOLLO_PORTAL_ENVS: ${APOLLO_PORTAL_ENVS} DEV_META: ${DEV_META} PRO_META: ${PRO_META} volumes: - /tmp/logs:/opt/logs
在上述的配置中,config和admin容器需要为每个环境单独配置,故有两个;而所有环境共用一个portal容器。这两个配置文件在源代码的资源目录下保存了一份供参考。
需要注意的是,config容器的默认端口是8080,由于在同一台机器上,需要修改其启动的端口,从而注册到Eureka中。这点很重要,对于多台机器,每台部署一个环境时,可不用修改。
4.4启动容器
启动命令:
docker-compose up -d
启动可能比较慢,待所有容器完全启动成功后,访问http://192.168.86.128:8070并登录。然后创建一个项目(请参考上一章节的说明,app.id等信息保持不变),如下图:
可以看到,在左侧的环境列表中,显示了配置的所有的环境。需要给每个环境新增配置并发布。
4.5测试
还是以上面的代码为例进行说明:
1)测试dev环境
在上面的配置中,dev环境对应的config的端口是8080,故把配置文件的url改成:
apollo.meta=http://192.168.86.128:8080
然后启动项目,访问http://localhost:8080/test/get,获取的是dev环境的值
2)测试pro环境
在上面的配置中,pro环境对应的config的端口是8081,故把配置文件的url改成:
apollo.meta=http://192.168.86.128:8081
然后启动项目,访问http://localhost:8080/test/get,获取的是pro环境的值