Apollo 是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
产品特色
- 分布式配置管理:在微服务架构中,应用程序可能分为多个微服务组件。Apollo可以帮助开发者集中管理这些微服务的配置信息,实现配置的统一化和集中化。
- 动态配置更新:Apollo支持在线修改配置并实时推送到各个客户端,无需重新部署应用程序。这有助于提高系统的灵活性和可维护性。
- 多环境和多集群配置支持:Apollo允许在不同环境(如开发、测试、生产等)和不同集群下管理配置信息。这有助于开发者在不同场景下灵活地使用和管理配置。
- 灰度发布:Apollo支持配置的灰度发布,允许开发者逐步推出新的配置更改,以便更好地控制风险和观察配置更改的影响。
- 权限管理和审计:Apollo提供了完善的权限管理和操作审计功能,有助于保证配置信息的安全和准确。
- 高可用性和容错性:Apollo采用分布式部署,确保了系统的高可用性和容错性。
贴上一张官方的结构图
image.png
这张图现在看,疑惑是正常的,那么就接着文章继续往下看
主要模块解析
- Portal Service 前端web管理界面,提供可视化的配置管理界面,支持配置的添加、修改、删除等操作,并能够对配置进行版本控制和历史回滚,通过IP+Port访问服务
- Config Service 提供配置的读取、推送等功能,提供配置更新推送接口(基于Http long polling),服务对象是Apollo客户端
对于负载是否会大的设计
- 服务端使用Spring DeferredResult实现异步化,从而大大增加长连接数量
- 目前使用的tomcat embed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)
- Admin Service 提供配置的修改、发布等功能,服务对象是 Portal(管理界面)
- Eureka 项目依赖于微服务,Config Service和Admin Service会向Eureka注册服务,并保持心跳,目前Eureka在部署时和Config Service是在一个JVM进程中的
- Client 业务代码客户端拉取配置,通过IP+Port访问服务
部署
环境依赖: java1.8+,Centos7(windows可选择Quick Start方式体验),mysql5.6.5+
本文将分部署部署2个节点,从而体验2个环境的应用,我们通过不同端口的方法,来模拟2个linux服务器,为此准备了
10.0.50.20 linux服务器,运行Apollo服务
10.0.54.9 mysql服务器
10.0.50.65 mysql服务器
创建数据库
Apollo服务端共需要两个数据库:ApolloPortalDB和ApolloConfigDB,我们把数据库、表的创建和样例数据都分别准备了sql文件,只需要导入数据库即可。
ApolloPortalDB 大多提供了
Portal Server管理界面的配置,里面继承了多维度(例如环境、节点配置)的管理,所以只需要在生产环境部署一个即可
1.1 10.0.54.9创建ApolloPortalDB数据库
1.2 导入数据https://github.com/apolloconfig/apollo/blob/master/scripts/sql/apolloportaldb.sqlApolloConfigDB 需要在每个环境部署一套,如dev、uat和pro分别部署3套ApolloConfigDB,属于各个节点的业务存储
2.1 10.0.54.9和10.0.50.65分别创建ApolloConfigDB数据库
2.2 分别导入数据https://github.com/apolloconfig/apollo/blob/master/scripts/sql/apolloconfigdb.sql
下载安装包
本文演示 Apollo 2.0.1 版本
地址 https://github.com/apolloconfig/apollo/releases,Assets模块有java源码及打包好的jar两种类型的链接,这里我们下载打包好的安装包来省去我们本地编译过程
下载三个安装包到 10.0.50.20 服务器
apollo-adminservice-2.0.1-github.zip、apollo-configservice-2.0.1-github.zip、apollo-portal-2.0.1-github.zip
部署配置安装包
10.0.50.20 服务器,/home/www/configCenter目录下新建5个文件夹 admin、admin_2、config、config_2、portal
- 文件夹 admin,节点1的 Admin Server服务
- 拷贝
apollo-adminservice-2.0.1-github.zip包到此目录下,并解压 - 修改
config/application-github.properties文件,此为节点1 Admin Server的ApolloConfigDB数据库句柄
# DataSource
spring.datasource.url = jdbc:mysql://10.0.54.9:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = saas_php
spring.datasource.password = 123QWEasd!@#
- 修改
scripts/startup.sh文件(此项为Admin Server监听端口,此步暂不修改)
SERVER_PORT=${SERVER_PORT:=8090}
- 文件夹 config,节点1的 Config Server服务
- 拷贝
apollo-configservice-2.1.0-github.zip包到此目录下,并解压 - 修改
config/application-github.properties文件,此为节点1 Config Server的ApolloConfigDB数据库句柄
# DataSource
spring.datasource.url = jdbc:mysql://10.0.54.9:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = saas_php
spring.datasource.password = 123QWEasd!@#
- 修改
scripts/startup.sh文件(此项为Config Server监听端口)
SERVER_PORT=${SERVER_PORT:=8086}
由于Apollo是基于eureka的微服务,另外apollo-configservice同时承担meta server职责,如果要修改端口,注意要同时ApolloConfigDB.ServerConfig表中的eureka.service.url配置项以及apollo-portal和apollo-client中的使用到的meta server信息
数据库10.0.54.9--ApolloConfigDb.ServerConfig表eureka.service.url值修改为http://localhost:8086/eureka/
meta server信息可在随后的portal后台,页面中配置

- 文件夹 admin_2,节点2的 Admin Server服务
- 拷贝
apollo-adminservice-2.0.1-github.zip包到此目录下,并解压 - 修改
config/application-github.properties文件,此为节点2 Admin Server的ApolloConfigDB数据库句柄
# DataSource
spring.datasource.url = jdbc:mysql://10.0.50.65:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = root
spring.datasource.password = 123456
- 修改
scripts/startup.sh文件(此项为Admin Server监听端口,此步暂不修改)
SERVER_PORT=${SERVER_PORT:=8088}
- 文件夹 config_2,节点2的 Config Server服务
- 拷贝
apollo-configservice-2.1.0-github.zip包到此目录下,并解压 - 修改
config/application-github.properties文件,此为节点2 Config Server的ApolloConfigDB数据库句柄
# DataSource
spring.datasource.url = jdbc:mysql://10.0.50.65:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = root
spring.datasource.password = 123456
- 修改
scripts/startup.sh文件(此项为Config Server监听端口)
SERVER_PORT=${SERVER_PORT:=8087}
此次也与节点1的 Config Server一样,需修改两个参数
数据库10.0.50.65--ApolloConfigDb.ServerConfig表eureka.service.url值修改为http://localhost:8087/eureka/
meta server信息可在随后的portal后台,页面中配置
- 文件夹 portal,portal Server服务
- 拷贝
apollo-portal-2.1.0-github.zip包到此目录下,并解压 - 修改
config/application-github.properties文件,此为 Portal Server 的ApolloPortalDB数据库句柄
# DataSource
spring.datasource.url = jdbc:mysql://10.0.54.9:3306/ApolloPortalDB?characterEncoding=utf8
spring.datasource.username = saas_php
spring.datasource.password = 123QWEasd!@#
- 本文演示dev fat两个环境,修改
config/apollo-env.properties文件
dev.meta=http://10.0.50.20:8086
fat.meta=http://10.0.50.20:8087
这里你会发现,此次的两个地址,正是我们上文中,节点1和节点2的 Config Server地址,此次配置这个原因为如下
3.1 Apollo Portal需要在不同的环境访问不同的meta service(apollo-configservice)地址,所以我们需要在配置中提供这些信息
3.2 默认情况下,meta service和Config Service是部署在同一个JVM进程,所以meta service的地址就是Config Service的地址。
好了,到此处,我们已经将准备工作全部就绪,接下来就是启动环节了,不急,我们再来整理一下
文件夹admin,存放节点1的Admin Server服务,监听端口8090
文件夹config,存放节点1的Config Server服务,监听端口8086
文件夹admin_2,存放节点2的Admin Server服务,监听端口8088
文件夹config_2,存放节点2的Config Server服务,监听端口8087
文件夹portal,存放全部节点的Portal Server服务,监听端口8070(scripts/startup.sh我们没有修改默认端口)
而节点1、2的eureka服务就是
http://10.0.50.20:8086/
http://10.0.50.20:8087/
是不是感觉多节点eureka服务是不是没必要各自启动,是的,但不在我们本文介绍中
此处,再来介绍一组概念,以Meta Server为引子
- Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port)
- Client通过域名访问Meta Server获取Config Service服务列表(IP+Port)
- Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
- 增设一个Meta Server的角色主要是为了封装服务发现的细节,对Portal和Client而言,永远通过一个Http接口获取Admin Service和Config Service的服务信息,而不需要关心背后实际的服务注册和发现组件
- Meta Server只是一个逻辑角色,在部署时和Config Service是在一个JVM进程中的,所以IP、端口和Config Service一致
启动服务
马上就要开启服务了,我相信看完此小结,就能理解上面的官方设计图了
- 启动节点1 Config Server服务
cd config/scripts/
./startup.sh
- 启动节点1 Admin Server服务
cd admin/scripts/
./startup.sh
- 启动节点2 Config Server服务
cd config_2/scripts/
./startup.sh
- 启动节点2 Admin Server服务
cd admin_2/scripts/
./startup.sh
- 启动portal Server服务
cd portal/scripts/
./startup.sh
现在,你可以打开浏览器输入http://10.0.50.20:8070/操作了
开始使用
还记得我们部署那步,让配置apollo.portal.meta.servers的步骤不,首页-管理员工具-系统参数-PortalDb配置
apollo.portal.meta.servers的值修改为{"DEV":"http://10.0.50.20:8086","FAT":"http://10.0.50.20:8087"},配置更新后,一分钟后自动生效,如果你不信任,可以选择portal/script目录下,两个shell脚本进行关闭、重启
环境显示为我们上面配置的dev和fat环境的ConfigServer服务配置项

我们创建两个应用苍龙一号 苍龙二号
需要注意的是,
首页-管理员工具-系统参数-PortalDb配置中有很丰富的配置项,比如部门、用户限制、key值大小长短等

以苍龙二号为例

注 application 为 namespaces,必填项,默认会创建名为application的空间
这里我们创建了一个配置参数token,左侧有dev和fat两个参数,客户端请求时
dev环境对应的地址为 10.0.50.20:8086
fat环境对应的地址为 10.0.50.20:8087
php客户端演示示例
composer require multilinguals/apollo-client
<?php
use Org\Multilinguals\Apollo\Client\ApolloClient;
function Handle() {
$server = '10.0.50.20:8087';
$appid = 13162568081;
$namespaces = ['application'];
$apollo = new ApolloClient($server, $appid, $namespaces);
if ($clientIp = getenv('CLIENTIP')) {
$apollo->setClientIp($clientIp);
}
ini_set('memory_limit','128M');
$pid = getmypid();
echo "start [$pid]\n";
$restart = true;
do {
$error = $apollo->start();
if ($error) {
echo('error:'.$error."\n");
sleep(1);
}
}while($error && $restart);
}
代码目录下会生成apolloConfig.application.php文件,并持续监听Apollo Portal 后台发布的配置
golang客户端演示示例
package main
import (
"fmt"
"github.com/shima-park/agollo"
)
func main() {
a, err := agollo.New("http://10.0.50.20:8087", "13162568081", agollo.PreloadNamespaces("application", "test.json"))
if err != nil {
panic(err)
}
errorCh := a.Start() // Start后会启动goroutine监听变化,并更新agollo对象内的配置cache
// 或者忽略错误处理直接 a.Start()
watchCh := a.Watch()
for {
select {
case errch := <-errorCh:
// handle error
panic(errch)
case resp := <-watchCh:
fmt.Println(
"Namespace:", resp.Namespace,
"OldValue:", resp.OldValue,
"NewValue:", resp.NewValue,
"Error:", resp.Error,
)
}
}
}
代码目录下会生成.agollo文件,并持续监听Apollo Portal 后台发布的配置
现在,我们再拿上一张官网的图,作为消化

谢谢你看完这篇文章,附上彩蛋一枚
竞品 https://www.jianshu.com/p/50cf94bcb5bb
体验地址 http://console.nacos.io/nacos/index.html
