文章目录
1. Apollo概念
随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关、参数的配置、服务器的地址……
对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境、分集群管理配置,完善的权限、审核机制……
在这样的大环境下,传统的通过配置文件、数据库等方式已经越来越无法满足开发人员对配置管理的需求。
Apollo配置中心应运而生!
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。
- 它是一个配置管理中心。
- 几乎实时更新。
- 多种加载方式。
- 环境维度的配置管理。
- 灰度发布。
… …
2. Apollo架构
整体架构
- Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
- Admin Service提供配置的修改、发布等功能,服务对象是Apollo Portal(管理界面)
- Config Service和Admin Service都是多实例、无状态部署,所以需要将自己注册到Eureka中并保持心跳
- 在Eureka之上我们架了一层Meta Server用于封装Eureka的服务发现接口
- Client通过域名访问Meta Server获取Config Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试
- Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Portal侧会做load balance、错误重试
- 为了简化部署,我们实际上会把Config Service、Eureka和Meta Server三个逻辑角色部署在同一个JVM进程中
客户端设计
- 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
- 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
- 这是一个fallback机制,为了防止推送机制失效导致配置不更新
- 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modified
- 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟。
- 客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
- 客户端会把从服务端获取到的配置在本地文件系统缓存一份
- 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
- 应用程序可以从Apollo客户端获取最新的配置、订阅配置更新通知
3.Apollo管理界面常用功能
新增应用
留意这里的应用id,后面接入时会用到。
新增namespace(配置文件)
namespace分为private(应用私有的)、public(所有应用公共的)、关联的(可以关联一个公共的namespace,然后覆盖其中的某些属性)
关联公共namespace
公共namespace
默认只支持.properties格式。
私有namespace
支持yml,properties等格式。
配置文件权限配置
4.Apollo客户端接入(以SpringBoot项目为例)
1. 引入依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>
2. 配置Apollo
1.设置appid
# application.yml中添加
app:
id: xxx
注:xxx为Apollo管理平台创建应用时设置的应用id
2. 配置Apollo使其生效
apollo:
bootstrap:
enabled: true
# 如果需要指定namespace,则需要如下配置。默认使用名为application的namespace
namespaces: application,FX.apollo,application.yml
3. 配置meta_server地址(Apollo Eurka地址)
- 通过Java system property ${env}_meta
- 如果当前env是dev,那么用户可以配置-Ddev_meta=http://config-service-url,如
- 使用该配置方式,那么就必须要正确配置Environment,详见4.4
- 通过操作系统的System Environment ${ENV}_META (1.2.0版本开始支持)
- 如果当前env是dev,那么用户可以配置操作系统的System Environment DEV_META=http://config-service-url
- 注意key为全大写
- 使用该配置方式,那么就必须要正确配置Environment,详见4.4
- 通过apollo-env.properties文件(推荐)
- 使用该配置方式,那么就必须要正确配置Environment,详见4.4
- resources目录下新建apollp-env.properties文件,内容如下
#开发环境
dev.meta=http://test-apollo-meta.com
#测试环境
fat.meta=http://test-apollo-meta.com
#生产环境
pro.meta=http://apollo-meta.com
4.指定使用的环境
- 通过Java System Property
- 可以通过Java的System Property env来指定环境
- 在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT,如:
- 如果是运行jar文件,需要注意格式是java -Denv=YOUR-ENVIRONMENT -jar xxx.jar
- 注意key为全小写
- 通过操作系统的System Environment
- 还可以通过操作系统的System Environment ENV来指定
- 注意key为全大写
- 通过配置文件(推荐)
- 对于Mac/Linux,配置文件位置为/opt/settings/server.properties(没有可以自行新建)
- 对于Windows,配置文件位置为C:\opt\settings\server.properties(没有可以自行新建)
- 通过配置文件来指定env=YOUR-ENVIRONMENT
- YOUR-ENVIRONMENT的值可取DEV(开发)、FAT(测试)、PRO(开发)
5. 添加属性配置
- 对于.properties格式的配置文件在Apollo平台上逐个添加
- 对于.properties和.yml格式的文件也可以批量添加
可以直接将项目已有的配置拷进来
- 配置保存成功以后需要点击【发布】按钮以使配置在应用中生效
至此,Apollo配置完毕!可以启动应用验证。
如果看到如下日志即配置成功,后续可以自己测试接口调用来确认。
5. 注意事项
- 对于简单的属性,修改配置之后可以自动更新,但是对于@ConfigurationProperties配置的属性,想要自动更新则需要【事件广播机制】,参考:ZuulPropertiesRefresher.java或者【RefreshScope】,参考SampleRedisConfig.java和SpringBootApolloRefreshConfig.java
推荐使用RefreshScope方式,具体使用时可以参考我的方式:
UserInfoConfig.java
@Component
@ConfigurationProperties(prefix = "my.user")
@RefreshScope
public class UserInfoConfig {
private String name;
private String nick;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
@Override
public String toString() {
return "UserInfoConfig{" +
"name='" + name + '\'' +
", nick='" + nick + '\'' +
'}';
}
}
SpringBootApolloRefreshConfig.java
@Component
public class SpringBootApolloRefreshConfig {
@Autowired
private UserInfoConfig userInfoConfig;
@Autowired
private RefreshScope refreshScope;
//apollo配置监听器,xxx.yml为要监听的配置文件(namespace)
@ApolloConfigChangeListener(value = {"xxx.yml"},
interestedKeyPrefixes = {"my.user."})
public void onChange(ConfigChangeEvent changeEvent) {
System.out.println("before refresh "+userInfoConfig.toString());
refreshScope.refresh("userInfoConfig");
System.out.println("after refresh "+userInfoConfig.toString());
}
}
- 要在Apollo平台配置yml格式的文件,对应apollo-client版本需要1.3.0以上