开源配置管理中心apollo使用方法
什么是apollo
Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
应用什么场景
项目在不同环境对应的不同的配置,统一管理不同环境、不同集群的配置
Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。 同一份代码部署在不同的集群,可以有不同的配置,比如zk的地址等 通过命名空间(namespace)可以很方便的支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
系统介绍
系统 | Centos7 |
---|---|
java环境 | java1.8 |
数据库 | MariaDB-10.2.9 |
IP | 192.168.1.8 |
使用文档
名词解释
普通应用 普通应用指的是独立运行的程序,如Web应用程序、带有main函数的程序
公共组件 公共组件指的是发布的类库、客户端程序,不会自己独立运行,如Java的jar包、.Net的dll文件
普通应用接入指南
创建项目
要使用Apollo,第一步需要创建项目。
- 打开apollo-portal主页
- 点击“创建项目”
- 输入项目信息
- 部门:选择应用所在的部门
- 应用AppId:用来标识应用身份的唯一id,格式为string,需要和客户端app.properties中配置的app.id对应
- 应用名称:应用名,仅用于界面展示
- 应用负责人:选择的人默认会成为该项目的管理员,具备项目权限管理、集群创建、Namespace创建等权限
- 点击提交 创建成功后,会自动跳转到项目首页
项目权限分配
项目管理员权限
项目管理员拥有以下权限:
- 可以管理项目的权限分配
- 可以创建集群
- 可以创建Namespace
创建项目时填写的应用负责人默认会成为项目的管理员之一,如果还需要其他人也成为项目管理员,可以按照下面步骤操作:
- 点击页面左侧的“管理项目”
- 搜索需要添加的成员并点击添加
配置编辑、发布权限
配置权限分为编辑和发布:
- 编辑权限允许用户在Apollo界面上创建、修改、删除配置
- 配置修改后只在Apollo界面上变化,不会影响到应用实际使用的配置
- 发布权限允许用户在Apollo界面上发布、回滚配置
- 配置只有在发布、回滚动作后才会被应用实际使用到
- Apollo在用户操作发布、回滚动作后实时通知到应用,并使最新配置生效
项目创建完,默认没有分配配置的编辑和发布权限,需要项目管理员进行授权。
- 点击application这个namespace的授权按钮
- 分配修改权限
- 分配发布权限
添加配置项
编辑配置需要拥有这个Namespace的编辑权限,如果发现没有新增配置按钮,可以找项目管理员授权。
通过表格模式添加配置
- 点击新增配置
- 输入配置项
- 点击提交
通过文本模式编辑
Apollo除了支持表格模式,逐个添加、修改配置外,还提供文本模式批量添加、修改。 这个对于从已有的properties文件迁移尤其有用。
- 切换到文本编辑模式
- 点击右侧的修改配置按钮
- 输入配置项,并点击提交修改
发布配置
配置只有在发布后才会真的被应用使用到,所以在编辑完配置后,需要发布配置。
发布配置需要拥有这个Namespace的发布权限,如果发现没有发布按钮,可以找项目管理员授权。
- 点击“发布按钮”
- 填写发布相关信息,点击发布
应用读取配置
配置发布成功后,应用就可以通过Apollo客户端读取到配置了。
Apollo目前提供Java客户端,具体信息请点击Java客户端使用文档:
如果应用使用了其它语言,也可以通过直接访问Http接口获取配置,具体可以参考其它语言客户端接入指南
应用接入Apollo
首先需要在Apollo中接入你的应用,具体步骤可以参考应用接入文档。
通过带缓存的Http接口从Apollo读取配置
该接口会从缓存中获取配置,适合频率较高的配置拉取请求,如简单的每30秒轮询一次配置。
由于缓存最多会有一秒的延时,所以如果需要配合配置推送通知实现实时更新配置的话,请参考通过不带缓存的Http接口从Apollo读取配置
Http接口说明
URL: {config_server_url}/configfiles/json/{appId}/{clusterName}/{namespaceName}?ip={clientIp}
Method: GET
参数说明:
参数名 | 是否必须 | 参数值 | 备注 |
---|---|---|---|
config_server_url | 是 | Apollo配置服务的地址 | |
appId | 是 | 应用的appId | |
clusterName | 是 | 集群名 | 一般情况下传入 default 即可。 如果希望配置按集群划分,可以参考集群独立配置说明做相关配置,然后在这里填入对应的集群名。 |
namespaceName | 是 | Namespace的名字 | 如果没有新建过Namespace的话,传入application即可。 如果创建了Namespace,并且需要使用该Namespace的配置,则传入对应的Namespace名字。需要注意的是对于properties类型的namespace,只需要传入namespace的名字即可,如application。对于其它类型的namespace,需要传入namespace的名字加上后缀名,如datasources.json |
ip | 否 | 应用部署的机器ip | 这个参数是可选的,用来实现灰度发布。 如果不想传这个参数,请注意URL中从?号开始的query parameters整个都不要出现。 |
Http接口返回格式
该Http接口返回的是JSON格式、UTF-8编码,包含了对应namespace中所有的配置项。
返回内容Sample如下:
代码语言:javascript复制{
"portal.elastic.document.type":"biz",
"portal.elastic.cluster.name":"hermes-es-fws"
}
通过
{config_server_url}/configfiles/{appId}/{clusterName}/{namespaceName}?ip={clientIp}
可以获取到properties形式的配置
测试
由于是Http接口,所以在URL组装OK之后,直接通过浏览器、或者相关的http接口测试工具访问即可。
本地测试:
代码语言:javascript复制# curl http://192.168.1.5:8080/configfiles/json/1001/default/application
{"redis_ip":"192.168.1.12","redis_passwd":"123456","redis_port":"6379"}
通过不带缓存的Http接口从Apollo读取配置
该接口会直接从数据库中获取配置,可以配合配置推送通知实现实时更新配置。
Http接口说明
URL: {config_server_url}/configs/{appId}/{clusterName}/{namespaceName}?releaseKey={releaseKey}&ip={clientIp}
Method: GET
参数说明:
参数名 | 是否必须 | 参数值 | 备注 |
---|---|---|---|
config_server_url | 是 | Apollo配置服务的地址 | |
appId | 是 | 应用的appId | |
clusterName | 是 | 集群名 | 一般情况下传入 default 即可。 如果希望配置按集群划分,可以参考集群独立配置说明做相关配置,然后在这里填入对应的集群名。 |
namespaceName | 是 | Namespace的名字 | 如果没有新建过Namespace的话,传入application即可。 如果创建了Namespace,并且需要使用该Namespace的配置,则传入对应的Namespace名字。需要注意的是对于properties类型的namespace,只需要传入namespace的名字即可,如application。对于其它类型的namespace,需要传入namespace的名字加上后缀名,如datasources.json |
releaseKey | 否 | 上一次的releaseKey | 将上一次返回对象中的releaseKey传入即可,用来给服务端比较版本,如果版本比下来没有变化,则服务端直接返回304以节省流量和运算 |
ip | 否 | 应用部署的机器ip | 这个参数是可选的,用来实现灰度发布。 |
Http接口返回格式
该Http接口返回的是JSON格式、UTF-8编码。
如果配置没有变化(传入的releaseKey和服务端的相等),则返回HttpStatus 304,response body为空。
如果配置有变化,则会返回HttpStatus 200,response body为对应namespace的meta信息以及其中所有的配置项。
返回内容Sample如下:
代码语言:javascript复制{
"appId": "100004458",
"cluster": "default",
"namespaceName": "application",
"configurations": {
"portal.elastic.document.type":"biz",
"portal.elastic.cluster.name":"hermes-es-fws"
},
"releaseKey": "20170430092936-dee2d58e74515ff3"
}
测试
由于是Http接口,所以在URL组装OK之后,直接通过浏览器、或者相关的http接口测试工具访问即可。
本地测试
代码语言:javascript复制# curl http://192.168.1.5:8080/configs/1001/default/application
{"appId":"1001","cluster":"default","namespaceName":"application","configurations":{"redis_ip":"192.168.1.12","redis_passwd":"123456","redis_port":"6379"},"releaseKey":"20220330100056-d3ee492df675126d"}
# curl http://192.168.1.5:8080/configs/1001/default/application?releaseKey=20220330100056-d3ee492df675126d
应用感知配置更新
Apollo提供了基于Http long polling的配置更新推送通知,第三方客户端可以看自己实际的需求决定是否需要使用这个功能。
如果对配置更新时间不是那么敏感的话,可以通过定时刷新来感知配置更新,刷新频率可以视应用自身情况来定,建议在30秒以上。
如果需要做到实时感知配置更新(1秒)的话,可以参考下面的文档实现配置更新推送的功能。
配置更新推送实现思路
这里建议大家可以参考Apollo的Java实现:RemoteConfigLongPollService.java,代码量200多行,总体上还是比较简单的。
初始化
首先需要确定哪些namespace需要配置更新推送,Apollo的实现方式是程序第一次获取某个namespace的配置时就会来注册一下,我们就知道有哪些namespace需要配置更新推送了。
初始化后的结果就是得到一个notifications的Map,内容是namespaceName -> notificationId(初始值为-1)。
运行过程中如果发现有新的namespace需要配置更新推送,直接塞到notifications这个Map里面即可。
请求服务
有了notifications这个Map之后,就可以请求服务了。这里先描述一下请求服务的逻辑,具体的URL参数和说明请参见后面的接口说明。
- 请求远端服务,带上自己的应用信息以及notifications信息
- 服务端针对传过来的每一个namespace和对应的notificationId,检查notificationId是否是最新的
- 如果都是最新的,则保持住请求60秒,如果60秒内没有配置变化,则返回HttpStatus 304。如果60秒内有配置变化,则返回对应namespace的最新notificationId, HttpStatus 200。
- 如果传过来的notifications信息中发现有notificationId比服务端老,则直接返回对应namespace的最新notificationId, HttpStatus 200。
- 客户端拿到服务端返回后,判断返回的HttpStatus
- 如果返回的HttpStatus是304,说明配置没有变化,重新执行第1步
- 如果返回的HttpStauts是200,说明配置有变化,针对变化的namespace重新去服务端拉取配置,参见1.3 通过不带缓存的Http接口从Apollo读取配置。同时更新notifications map中的notificationId。重新执行第1步。
Http接口说明
URL: {config_server_url}/notifications/v2?appId={appId}&cluster={clusterName}¬ifications={notifications}
Method: GET
参数说明:
参数名 | 是否必须 | 参数值 | 备注 |
---|---|---|---|
config_server_url | 是 | Apollo配置服务的地址 | |
appId | 是 | 应用的appId | |
clusterName | 是 | 集群名 | 一般情况下传入 default 即可。 如果希望配置按集群划分,可以参考集群独立配置说明做相关配置,然后在这里填入对应的集群名。 |
notifications | 是 | notifications信息 | 传入本地的notifications信息,注意这里需要以array形式转为json传入,如:[{"namespaceName": "application", "notificationId": 100}, {"namespaceName": "FX.apollo", "notificationId": 200}]。需要注意的是对于properties类型的namespace,只需要传入namespace的名字即可,如application。对于其它类型的namespace,需要传入namespace的名字加上后缀名,如datasources.json |
注1:由于服务端会hold住请求60秒,所以请确保客户端访问服务端的超时时间要大于60秒。
注2:别忘了对参数进行url encode
Http接口返回格式
该Http接口返回的是JSON格式、UTF-8编码,包含了有变化的namespace和最新的notificationId。
返回内容Sample如下:
代码语言:javascript复制[
{
"namespaceName": "application",
"notificationId": 101
}
]
测试
由于是Http接口,所以在URL组装OK之后,直接通过浏览器、或者相关的http接口测试工具访问即可。
配置访问密钥
Apollo从1.6.0版本开始增加访问密钥机制,从而只有经过身份验证的客户端才能访问敏感配置。如果应用开启了访问密钥,客户端发出请求时需要增加签名,否则无法获取配置。
需要设置的Header信息:
Header | Value | 备注 |
---|---|---|
Authorization | Apollo ${appId}:${signature} | appId: 应用的appId,signature:使用访问密钥对当前时间以及所访问的URL加签后的值,具体实现可以参考Signature.signature |
Timestamp | 从1970-1-1 00:00:00 UTC 0到现在所经过的毫秒数 | 可以参考System.currentTimeMillis |
本地测试
代码语言:javascript复制# curl
http://192.168.1.5:8080/configfiles/json/1001/default/application
{"timestamp":"2022-03-30T16:39:11.912 0800","status":401,"error":"Unauthorized","message":"","path":"/configfiles/json/1001/default/application"}
报错 401
密钥: da01f4aab45d4e3c8b8764d99f9a31f5
获取时间戳: Timestamp=`date %s`
curl http://192.168.1.5:8080/configfiles/json/1001/default/application -X POST -H "Content-type:application/json" -d '{"Authorization":"Apollo 1001:da01f4aab45d4e3c8b8764d99f9a31f5","Timestamp":"1648630422"}'
错误码说明
正常情况下,接口返回的Http状态码是200,下面列举了Apollo会返回的非200错误码说明。
400 - Bad Request
客户端传入参数的错误,如必选参数没有传入等,客户端需要根据提示信息检查对应的参数是否正确。
401 - Unauthorized
客户端未授权,如服务端配置了访问密钥,客户端未配置或配置错误。
404 - Not Found
接口要访问的资源不存在,一般是URL或URL的参数错误,或者是对应的namespace还没有发布过配置。
405 - Method Not Allowed
接口访问的Method不正确,比如应该使用GET的接口使用了POST访问等,客户端需要检查接口访问方式是否正确。
500 - Internal Server Error
其它类型的错误默认都会返回500,对这类错误如果应用无法根据提示信息找到原因的话,可以尝试查看服务端日志来排查问题。
Apollo使用场景和示例代码
https://github.com/ctripcorp/apollo-use-cases
Apollo 实践案例
- Apollo ES源码改造,构建民生银行的ELK日志平台配置管理中心
- Apollo在有赞的实践
- 微服务版本切换初始设计思路
- Alibaba Sentinel Push模式 规则推送至Apollo配置中心
Apollo 安全相关最佳实践
配置查看权限
从1.1.0版本开始,apollo-portal增加了查看权限的支持,可以支持配置某个环境只允许项目成员查看私有Namespace的配置。
这里的项目成员是指:
- 项目的管理员
- 具备该私有Namespace在该环境下的修改或发布权限
配置方式很简单,用超级管理员账号登录后,进入管理员工具 - 系统参数
页面新增或修改configView.memberOnly.envs
配置项即可。
配置访问密钥
Apollo从1.6.0版本开始增加访问密钥机制,从而只有经过身份验证的客户端才能访问敏感配置。如果应用开启了访问密钥,客户端需要配置密钥,否则无法获取配置。
- 项目管理员打开管理密钥页面
- 为项目的每个环境生成访问密钥,注意默认是禁用的,建议在客户端都配置完成后再开启
客户端配置访问密钥
适用于1.6.0及以上版本
Apollo从1.6.0版本开始增加访问密钥机制,从而只有经过身份验证的客户端才能访问敏感配置。如果应用开启了访问密钥,客户端需要配置密钥,否则无法获取配置。
配置方式按照优先级从高到低分别为:
1.通过Java System Property
代码语言:javascript复制 通过Java System Propertyapollo.access-key.secret(1.9.0 ) 或者 apollo.accesskey.secret(1.9.0之前)
可以通过Java的System Property apollo.access-key.secret(1.9.0 ) 或者 apollo.accesskey.secret(1.9.0之前)来指定
在Java程序启动脚本中,可以指定-Dapollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0 ) 或者 -Dapollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0之前)
如果是运行jar文件,需要注意格式是java -Dapollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719 -jar xxx.jar(1.9.0 ) 或者 java -Dapollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719 -jar xxx.jar(1.9.0之前)
也可以通过程序指定,如System.setProperty("apollo.access-key.secret", "1cf998c4e2ad4704b45a98a509d15719");(1.9.0 ) 或者 System.setProperty("apollo.accesskey.secret", "1cf998c4e2ad4704b45a98a509d15719");(1.9.0之前)
2.通过Spring Boot的配置文件
代码语言:javascript复制 可以在Spring Boot的application.properties或bootstrap.properties中指定apollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0 ) 或者 apollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0之前)
3.通过操作系统的System Environment
代码语言:javascript复制还可以通过操作系统的System Environment APOLLO_ACCESS_KEY_SECRET(1.9.0 ) 或者 APOLLO_ACCESSKEY_SECRET(1.9.0之前)来指定
注意key为全大写
4.通过app.properties配置文件
代码语言:javascript复制 可以在classpath:/META-INF/app.properties指定apollo.access-key.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0 ) 或者 apollo.accesskey.secret=1cf998c4e2ad4704b45a98a509d15719(1.9.0之前)
自定义server.properties路径
适用于1.8.0及以上版本
1.8.0版本开始支持以下方式自定义server.properties路径,按照优先级从高到低分别为:
一.通过Java System Property apollo.path.server.properties
代码语言:javascript复制1.可以通过Java的System Property apollo.path.server.properties来指定
2.在Java程序启动脚本中,可以指定-Dapollo.path.server.properties=/some-dir/some-file.properties
如果是运行jar文件,需要注意格式是java -Dapollo.path.server.properties=/some-dir/some-file.properties -jar xxx.jar
3.也可以通过程序指定,如System.setProperty("apollo.path.server.properties", "/some-dir/some-file.properties");
二、通过操作系统的System EnvironmentAPOLLO_PATH_SERVER_PROPERTIES
代码语言:javascript复制可以通过操作系统的System Environment APOLLO_PATH_SERVER_PROPERTIES来指定
注意key为全大写,且中间是_分隔
客户端用法
Apollo支持API方式和Spring整合方式,该怎么选择用哪一种方式?
- API方式灵活,功能完备,配置值实时更新(热发布),支持所有Java环境。
- Spring方式接入简单,结合Spring有N种酷炫的玩法,如
- Placeholder方式:
- 代码中直接使用,如:
@Value("${someKeyFromApollo:someDefaultValue}")
- 配置文件中使用替换placeholder,如:
spring.datasource.url: ${someKeyFromApollo:someDefaultValue}
- 直接托管spring的配置,如在apollo中直接配置
spring.datasource.url=jdbc:mysql://localhost:3306/somedb?characterEncoding=utf8
- 代码中直接使用,如:
- Spring boot的@ConfigurationProperties方式
- 从v0.10.0开始的版本支持placeholder在运行时自动更新,具体参见PR #972。(v0.10.0之前的版本在配置变化后不会重新注入,需要重启才会更新,如果需要配置值实时更新,可以参考后续3.2.2 Spring Placeholder的使用的说明)
- Placeholder方式:
- Spring方式也可以结合API方式使用,如注入Apollo的Config对象,就可以照常通过API方式获取配置了: @ApolloConfig private Config config; //inject config for namespace application点击复制错误复制成功
API使用方式
API方式是最简单、高效使用Apollo配置的方式,不依赖Spring框架即可使用。
获取默认namespace的配置(application)
代码语言:javascript复制Config config = ConfigService.getAppConfig(); //config instance is singleton for each namespace and is never null
String someKey = "someKeyFromDefaultNamespace";
String someDefaultValue = "someDefaultValueForTheKey";
String value = config.getProperty(someKey, someDefaultValue);
通过上述的config.getProperty可以获取到someKey对应的实时最新的配置值。
另外,配置值从内存中获取,所以不需要应用自己做缓存。
Go、Python、Nodejs、PHP等客户端使用
对应开发语言支持:https://www.apolloconfig.com/#/zh/usage/third-party-sdks-user-guide
Apollo PHP 客户端 1
项目地址:apollo-php-client
Apollo PHP 客户端 2
项目地址:apollo-sdk-config
项目地址:apollo-sdk-clientd
什么是Namespace
Namespace是配置项的集合,类似于一个配置文件的概念。
个人觉得也是Apollo的比较重要和核心的知识点!
什么是“application”的Namespace
Apollo在创建项目的时候,都会默认创建一个“application”的Namespace。顾名思义,“application”是给应用自身使用的,熟悉Spring Boot的同学都知道,Spring Boot项目都有一个默认配置文件application.yml。在这里application.yml就等同于“application”的Namespace。对于90%的应用来说,“application”的Namespace已经满足日常配置使用场景了。
客户端获取“application” Namespace的代码如下:
代码语言:javascript复制 Config config = ConfigService.getAppConfig();
客户端获取非“application” Namespace的代码如下:
代码语言:javascript复制 Config config = ConfigService.getConfig(namespaceName);
Namespace的格式有哪些?
配置文件有多种格式,例如:properties、xml、yml、yaml、json等。同样Namespace也具有这些格式。在Portal UI中可以看到“application”的Namespace上有一个“properties”标签,表明“application”是properties格式的。
注1:非properties格式的namespace,在客户端使用时需要调用
ConfigService.getConfigFile(String namespace, ConfigFileFormat configFileFormat)
来获取,如果使用Http接口直接调用时,对应的namespace参数需要传入namespace的名字加上后缀名,如datasources.json。注2:apollo-client 1.3.0版本开始对yaml/yml做了更好的支持,使用起来和properties格式一致:
Config config = ConfigService.getConfig("application.yml");
,Spring的注入方式也和properties一致。
Namespace的获取权限分类
private (私有的)
public (公共的)
这里的获取权限是相对于Apollo客户端来说的。
private权限的Namespace:只能被所属的应用获取到。一个应用尝试获取其它应用private的Namespace,Apollo会报“404”异常。
public权限的Namespace: 能被任何应用获取。
Namespace的类型
Namespace类型有三种:
私有类型
具有private权限。例如上文提到的“application” Namespace就是私有类型。
公共类型
具有public权限。公共类型的Namespace相当于游离于应用之外的配置,且通过Namespace的名称去标识公共Namespace,所以公共的Namespace的名称必须全局唯一。
使用场景:部门级别共享的配置、小组级别共享的配置、几个项目之间共享的配置、中间件客户端的配置。
关联类型(继承类型)
关联类型又可称为继承类型,关联类型具有private权限。关联类型的Namespace继承于公共类型的Namespace,用于覆盖公共Namespace的某些配置。
例如公共的Namespace有两个配置项
代码语言:javascript复制k1 = v1
k2 = v2
然后应用A有一个关联类型的Namespace关联了此公共Namespace,且覆盖了配置项k1,新值为v3。那么在应用A实际运行时,获取到的公共Namespace的配置为:
代码语言:javascript复制k1 = v3
k2 = v2
关联类型使用场景:
举一个实际使用的场景。假设RPC框架的配置(如:timeout)有以下要求:
- 提供一份全公司默认的配置且可动态调整
- RPC客户端项目可以自定义某些配置项且可动态调整
- 如果把以上两点要求去掉“动态调整”,那么做法很简单。在rpc-client.jar包里有一份配置文件,每次修改配置文件然后重新发一个版本的jar包即可。同理,客户端项目修改配置也是如此。
- 如果只支持客户端项目可动态调整配置。客户端项目可以在Apollo “application” Namespace上配置一些配置项。在初始化service的时候,从Apollo上读取配置即可。这样做的坏处就是,每个项目都要自定义一些key,不统一。
- 那么如何完美支持以上需求呢?答案就是结合使用Apollo的公共类型的Namespace和关联类型的Namespace。RPC团队在Apollo上维护一个叫“rpc-client”的公共Namespace,在“rpc-client” Namespace上配置默认的参数值。rpc-client.jar里的代码读取“rpc-client”Namespace的配置即可。如果需要调整默认的配置,只需要修改公共类型“rpc-client” Namespace的配置。如果客户端项目想要自定义或动态修改某些配置项,只需要在Apollo 自己项目下关联“rpc-client”,就能创建关联类型“rpc-client”的Namespace。然后在关联类型“rpc-client”的Namespace下修改配置项即可。这里有一点需要指出的,那就是rpc-client.jar是在应用容器里运行的,所以rpc-client获取到的“rpc-client” Namespace的配置是应用的关联类型的Namespace加上公共类型的Namespace。
例子
如下图所示,有三个应用:应用A、应用B、应用C。
- 应用A有两个私有类型的Namespace:application和NS-Private,以及一个关联类型的Namespace:NS-Public。
- 应用B有一个私有类型的Namespace:application,以及一个公共类型的Namespace:NS-Public。
- 应用C只有一个私有类型的Namespace:application
应用A获取Apollo配置
代码语言:javascript复制 //application
Config appConfig = ConfigService.getAppConfig();
appConfig.getProperty("k1", null); // k1 = v11
appConfig.getProperty("k2", null); // k2 = v21
//NS-Private
Config privateConfig = ConfigService.getConfig("NS-Private");
privateConfig.getProperty("k1", null); // k1 = v3
privateConfig.getProperty("k3", null); // k3 = v4
//NS-Public,覆盖公共类型配置的情况,k4被覆盖
Config publicConfig = ConfigService.getConfig("NS-Public");
publicConfig.getProperty("k4", null); // k4 = v6 cover
publicConfig.getProperty("k6", null); // k6 = v6
publicConfig.getProperty("k7", null); // k7 = v7点击复制错误复制成功
应用B获取Apollo配置
代码语言:javascript复制 //application
Config appConfig = ConfigService.getAppConfig();
appConfig.getProperty("k1", null); // k1 = v12
appConfig.getProperty("k2", null); // k2 = null
appConfig.getProperty("k3", null); // k3 = v32
//NS-Private,由于没有NS-Private Namespace 所以获取到default value
Config privateConfig = ConfigService.getConfig("NS-Private");
privateConfig.getProperty("k1", "default value");
//NS-Public
Config publicConfig = ConfigService.getConfig("NS-Public");
publicConfig.getProperty("k4", null); // k4 = v5
publicConfig.getProperty("k6", null); // k6 = v6
publicConfig.getProperty("k7", null); // k7 = v7点击复制错误复制成功
应用C获取Apollo配置
代码语言:javascript复制 //application
Config appConfig = ConfigService.getAppConfig();
appConfig.getProperty("k1", null); // k1 = v12
appConfig.getProperty("k2", null); // k2 = null
appConfig.getProperty("k3", null); // k3 = v33
//NS-Private,由于没有NS-Private Namespace 所以获取到default value
Config privateConfig = ConfigService.getConfig("NS-Private");
privateConfig.getProperty("k1", "default value");
//NS-Public,公共类型的Namespace,任何项目都可以获取到
Config publicConfig = ConfigService.getConfig("NS-Public");
publicConfig.getProperty("k4", null); // k4 = v5
publicConfig.getProperty("k6", null); // k6 = v6
publicConfig.getProperty("k7", null); // k7 = v7点击复制错误复制成功
ChangeListener
以上代码例子中可以看到,在客户端Namespace映射成一个Config对象。Namespace配置变更的监听器是注册在Config对象上。
所以在应用A中监听application的Namespace代码如下:
代码语言:javascript复制Config appConfig = ConfigService.getAppConfig();
appConfig.addChangeListener(new ConfigChangeListener() {
public void onChange(ConfigChangeEvent changeEvent) {
//do something
}
})
在应用A中监听NS-Private的Namespace代码如下:
代码语言:javascript复制Config privateConfig = ConfigService.getConfig("NS-Private");
privateConfig.addChangeListener(new ConfigChangeListener() {
public void onChange(ConfigChangeEvent changeEvent) {
//do something
}
})
在应用A、应用B、应用C中监听NS-Public的Namespace代码如下:
代码语言:javascript复制Config publicConfig = ConfigService.getConfig("NS-Public");
publicConfig.addChangeListener(new ConfigChangeListener() {
public void onChange(ConfigChangeEvent changeEvent) {
//do something
}
})
调整ApolloConfigDB配置
配置项统一存储在ApolloConfigDB.ServerConfig表中,需要注意每个环境的ApolloConfigDB.ServerConfig都需要单独配置,修改完一分钟实时生效。
namespace.lock.switch - 一次发布只能有一个人修改开关,用于发布审核
这是一个功能开关,如果配置为true的话,那么一次配置发布只能是一个人修改,另一个发布。
生产环境建议开启此选项
服务端配置说明
以下配置除了支持在数据库中配置以外,也支持通过-D参数、application.properties等配置,且-D参数、application.properties等优先级高于数据库中的配置
调整ApolloPortalDB配置
配置项统一存储在ApolloPortalDB.ServerConfig表中,也可以通过管理员工具 - 系统参数
页面进行配置,无特殊说明则修改完一分钟实时生效。
apollo.portal.envs - 可支持的环境列表
默认值是dev,如果portal需要管理多个环境的话,以逗号分隔即可(大小写不敏感),如:
代码语言:javascript复制DEV,FAT,UAT,PRO
名词解释:
代码语言:javascript复制DEV(Development environment)
开发环境,用于开发者调试使用
FAT(Feature Acceptance Test environment)
功能验收测试环境,用于软件测试者测试使用
UAT(User Acceptance Test environment)
用户验收测试环境,用于用户测试验收使用
PRO(Production environment)
生产环境
修改完需要重启生效。
注1:一套Portal可以管理多个环境,但是每个环境都需要独立部署一套Config Service、Admin Service和ApolloConfigDB,具体请参考:2.1.2 创建ApolloConfigDB,3.2 调整ApolloConfigDB配置,2.2.1.1.2 配置数据库连接信息,另外如果是为已经运行了一段时间的Apollo配置中心增加环境,别忘了参考2.1.2.4 从别的环境导入ApolloConfigDB的项目数据对新的环境做初始化。
注2:只在数据库添加环境是不起作用的,还需要为apollo-portal添加新增环境对应的meta server地址,具体参考:2.2.1.1.2.4 配置apollo-portal的meta service信息。apollo-client在新的环境下使用时也需要做好相应的配置,具体参考:1.2.2 Apollo Meta Server。
注3:如果希望添加自定义的环境名称,具体步骤可以参考Portal如何增加环境。
注4:1.1.0版本增加了系统信息页面(
管理员工具
->系统信息
),可以通过该页面检查配置是否正确
多环境部署
配置apollo-portal的meta service信息
Apollo Portal需要在不同的环境访问不同的meta service(apollo-configservice)地址,所以我们需要在配置中提供这些信息。默认情况下,meta service和config service是部署在同一个JVM进程,所以meta service的地址就是config service的地址。
对于1.6.0及以上版本,可以通过ApolloPortalDB.ServerConfig中的配置项来配置Meta Service地址,详见apollo.portal.meta.servers - 各环境Meta Service列表
使用程序员专用编辑器(如vim,notepad ,sublime等)打开apollo-portal-x.x.x-github.zip
中config
目录下的apollo-env.properties
文件。
假设DEV的apollo-configservice未绑定域名,地址是192.168.1.5:8080,PRO的apollo-configservice绑定了域名apollo.chuanqu.ltd,那么可以如下修改各环境meta service服务地址,格式为${env}.meta=http://${config-service-url:port}
,如果某个环境不需要,也可以直接删除对应的配置项(如lpt.meta):
dev.meta=http://1.1.1.1:8080
fat.meta=http://apollo.fat.xxx.com
uat.meta=http://apollo.uat.xxx.com
pro.meta=http://apollo.xxx.com
除了通过apollo-env.properties
方式配置meta service以外,apollo也支持在运行时指定meta service(优先级比apollo-env.properties
高):
- 通过Java System Property
${env}_meta
- 可以通过Java的System Property
${env}_meta
来指定 - 如
java -Ddev_meta=http://config-service-url -jar xxx.jar
- 也可以通过程序指定,如
System.setProperty("dev_meta", "http://config-service-url");
- 可以通过Java的System Property
- 通过操作系统的System Environment
${ENV}_META
- 如
DEV_META=http://config-service-url
- 注意key为全大写,且中间是
_
分隔
- 如
注1: 为了实现meta service的高可用,推荐通过SLB(Software Load Balancer)做动态负载均衡
注2: meta service地址也可以填入IP,0.11.0版本之前只支持填入一个IP。从0.11.0版本开始支持填入以逗号分隔的多个地址(PR #1214),如
http://1.1.1.1:8080,http://2.2.2.2:8080
,不过生产环境还是建议使用域名(走slb),因为机器扩容、缩容等都可能导致IP列表的变化。