开源配置管理中心apollo使用方法

2022-05-28 13:35:44 浏览数 (2)

开源配置管理中心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,第一步需要创建项目。

  1. 打开apollo-portal主页
  2. 点击“创建项目”
  1. 输入项目信息
    • 部门:选择应用所在的部门
    • 应用AppId:用来标识应用身份的唯一id,格式为string,需要和客户端app.properties中配置的app.id对应
    • 应用名称:应用名,仅用于界面展示
    • 应用负责人:选择的人默认会成为该项目的管理员,具备项目权限管理、集群创建、Namespace创建等权限
  1. 点击提交 创建成功后,会自动跳转到项目首页

项目权限分配

项目管理员权限

项目管理员拥有以下权限:

  1. 可以管理项目的权限分配
  2. 可以创建集群
  3. 可以创建Namespace

创建项目时填写的应用负责人默认会成为项目的管理员之一,如果还需要其他人也成为项目管理员,可以按照下面步骤操作:

  1. 点击页面左侧的“管理项目”
  2. 搜索需要添加的成员并点击添加

配置编辑、发布权限

配置权限分为编辑和发布:

  • 编辑权限允许用户在Apollo界面上创建、修改、删除配置
    • 配置修改后只在Apollo界面上变化,不会影响到应用实际使用的配置
  • 发布权限允许用户在Apollo界面上发布、回滚配置
    • 配置只有在发布、回滚动作后才会被应用实际使用到
    • Apollo在用户操作发布、回滚动作后实时通知到应用,并使最新配置生效

项目创建完,默认没有分配配置的编辑和发布权限,需要项目管理员进行授权。

  1. 点击application这个namespace的授权按钮
  2. 分配修改权限
  3. 分配发布权限

添加配置项

编辑配置需要拥有这个Namespace的编辑权限,如果发现没有新增配置按钮,可以找项目管理员授权。

通过表格模式添加配置

  1. 点击新增配置
  2. 输入配置项
  3. 点击提交

通过文本模式编辑

Apollo除了支持表格模式,逐个添加、修改配置外,还提供文本模式批量添加、修改。 这个对于从已有的properties文件迁移尤其有用。

  1. 切换到文本编辑模式
  1. 点击右侧的修改配置按钮
  1. 输入配置项,并点击提交修改

发布配置

配置只有在发布后才会真的被应用使用到,所以在编辑完配置后,需要发布配置。

发布配置需要拥有这个Namespace的发布权限,如果发现没有发布按钮,可以找项目管理员授权。

  1. 点击“发布按钮”
  1. 填写发布相关信息,点击发布

应用读取配置

配置发布成功后,应用就可以通过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参数和说明请参见后面的接口说明。

  1. 请求远端服务,带上自己的应用信息以及notifications信息
  2. 服务端针对传过来的每一个namespace和对应的notificationId,检查notificationId是否是最新的
  3. 如果都是最新的,则保持住请求60秒,如果60秒内没有配置变化,则返回HttpStatus 304。如果60秒内有配置变化,则返回对应namespace的最新notificationId, HttpStatus 200。
  4. 如果传过来的notifications信息中发现有notificationId比服务端老,则直接返回对应namespace的最新notificationId, HttpStatus 200。
  5. 客户端拿到服务端返回后,判断返回的HttpStatus
  6. 如果返回的HttpStatus是304,说明配置没有变化,重新执行第1步
  7. 如果返回的HttpStauts是200,说明配置有变化,针对变化的namespace重新去服务端拉取配置,参见1.3 通过不带缓存的Http接口从Apollo读取配置。同时更新notifications map中的notificationId。重新执行第1步。

Http接口说明

URL: {config_server_url}/notifications/v2?appId={appId}&cluster={clusterName}&notifications={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的配置。

这里的项目成员是指:

  1. 项目的管理员
  2. 具备该私有Namespace在该环境下的修改或发布权限

配置方式很简单,用超级管理员账号登录后,进入管理员工具 - 系统参数页面新增或修改configView.memberOnly.envs配置项即可。

配置访问密钥

Apollo从1.6.0版本开始增加访问密钥机制,从而只有经过身份验证的客户端才能访问敏感配置。如果应用开启了访问密钥,客户端需要配置密钥,否则无法获取配置。

  1. 项目管理员打开管理密钥页面
  1. 为项目的每个环境生成访问密钥,注意默认是禁用的,建议在客户端都配置完成后再开启

客户端配置访问密钥

适用于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的使用的说明)
  • 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客户端项目可以自定义某些配置项且可动态调整
  1. 如果把以上两点要求去掉“动态调整”,那么做法很简单。在rpc-client.jar包里有一份配置文件,每次修改配置文件然后重新发一个版本的jar包即可。同理,客户端项目修改配置也是如此。
  2. 如果只支持客户端项目可动态调整配置。客户端项目可以在Apollo “application” Namespace上配置一些配置项。在初始化service的时候,从Apollo上读取配置即可。这样做的坏处就是,每个项目都要自定义一些key,不统一。
  3. 那么如何完美支持以上需求呢?答案就是结合使用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 创建ApolloConfigDB3.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.zipconfig目录下的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):

代码语言:javascript复制
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高):

  1. 通过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");
  2. 通过操作系统的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列表的变化。

0 人点赞