一、Apllo
1、Apollo介绍
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。
Apollo支持4个维度管理Key-Value格式的配置:
- application (应用)
- environment (环境)
- cluster (集群)
- namespace (命名空间)
2、Apollo的优势
- 统一管理不同环境、不同集群的配置
- 配置修改实时生效
- 版本发布管理
- 灰度发布
- 权限管理、发布审核、操作审计
- 客户端配置信息监控
- 部署简单,只依赖一个mysql
3、与Spring Cloud Config对比来体现出
4、Namespace
Namespace就相当于spring boot项目中的配置文件,例如namespace中有默认的application,格式为properties,则对应着application.properties。
1 Namespace的格式
配置文件有多种格式,例如:properties、xml、yml、yaml、json等。同样Namespace也具有这些格式。
2 Namespace的获取权限分类
Namespace的获取权限分为两种:
private (私有的)
public (公共的)
这里的获取权限是相对于Apollo客户端来说的。
3. Namespace的类型
Namespace类型有三种:
- 私有类型
- 公共类型
- 关联类型(继承类型)
3.1 私有类型
私有类型的Namespace具有private权限。例如上文提到的“application” Namespace就是私有类型。
3.2 公共类型
公共类型的Namespace具有public权限。公共类型的Namespace相当于游离于应用之外的配置,且通过Namespace的名称去标识公共Namespace,所以公共的Namespace的名称必须全局唯一。
使用场景
- 部门级别共享的配置
- 小组级别共享的配置
- 几个项目之间共享的配置
- 中间件客户端的配置
3.3 关联类型
关联类型又可称为继承类型,关联类型具有private权限。关联类型的Namespace继承于公共类型的Namespace,用于覆盖公共Namespace的某些配置。例如公共的Namespace有两个配置项
k1 = v1
k2 = v2
然后应用A有一个关联类型的Namespace关联了此公共Namespace,且覆盖了配置项k1,新值为v3。那么在应用A实际运行时,获取到的公共Namespace的配置为:
k1 = v3
k2 = v2
5、Apollo的客户端
Apollo支持基于Spring Boot、基于Java、基于XML等等多种方式的配置,具体详情可参考官网
Apollo会在本地存一份缓存配置文件
- Mac/Linux上文件位置为/opt/data/{appId}/config-cache
- Windows上文件位置为C:\opt\data{appId}\config-cache
- 本地配置文件会以{appId}+{cluster}+{namespace}.properties的文件名和格式存储,当获取不到网络配置时会从这个配置中取值
下面我就介绍最常用、简便、快捷、通用的方式,即基于Spring Boot的集成方式。
1 首先加入依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>
2 在服务应用的配置中加入以下配置(本例子中的文件为application.yml):
app:
id: test-app
apollo:
meta: http://localhost:8080
#cluster: myCluster
#cacheDir: /opt/testDir
bootstrap:
enable: true
namespaces: application
env: DEV
- app.id为在服务端web页面上创建的项目APP的id
- apollo.meta为apollo服务端的地址
- apollo.cluster为要配置的集群名称,如果没有可不填
- apollo.cacheDir为自定义缓存路径
- apollo.bootstrap.enable为是否在工程启动的bootstrap阶段向Spring容器注入被托管的namespaces中的配置
- apollo.bootstrap.namespaces为要使用的namespaces,可在web页面上看到
- env为要获取的配置环境,目前支持以下几个值(大小写不敏感):
- DEV(Development environment)
- FAT(Feature Acceptance Test environment)
- UAT(User Acceptance Test environment)
- PRO(Production environment)
在启动Spring Boot的java文件中添加注解:
@EnableApolloConfig
3 Apollo客户端的使用
1)简单配置
使用@Value注解的配置会自动刷新配置
2)复杂对象
方案一:
@Component("systemConfig")
@ConfigurationProperties(prefix = "system")
@EnableApolloConfig("system.yml")
public class SystemConfig {
private Resource filePath;
private Resource tempFilePath;
}
public class ApolloRefreshConfig implements ApplicationContextAware {
@Autowired
private SystemConfig systemConfig;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@ApolloConfigChangeListener(value = "system.yml",interestedKeyPrefixes="system")
private void configChange(ConfigChangeEvent changeEvent){
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
log.info("appConfig,{}",JSON.toJSONString( systemConfig));
}
方案二:
@Component("systemConfig")
@ConfigurationProperties(prefix = "cword")
@RefreshScope
@EnableApolloConfig("cword")
public class SystemConfig {
private Resource filePath;
private Resource tempFilePath;
@Autowired
private org.springframework.cloud.context.scope.refresh.RefreshScope refreshScope;
@ApolloConfigChangeListener("cword")
private void configChange(ConfigChangeEvent changeEvent){
refreshScope.refresh("systemConfig");
}
}
二、SpringCloudConfig
1、概述
whta
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用提供了一个中心化的外部配置。
how
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口。
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
why
- 集中管理配置文件
- 不同环境不同配置,动态化的配置更新,分布式部署,比如 dev/test/prod/beta/release
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取自己的信息
- 当配置发生变动时,服务不需要重启即可感知配置的变化并应用新的配置
- 将配置信息以REST接口的形式暴露:post,curl命令刷新
2、与Github整合部署
由于SpringCloud Config默认使用Git来存储配置文件(也有其他方式,比如支持SVN和本地文件),但最推荐的还是Git,而且使用的是Http/https访问的形式
3、存在的问题
- Linux运维修改Github上的配置文件内容做调整
- 刷新3344,发现ConfigServer配置中心立刻响应
- 刷新3355,发现ConfigClient客户端没有任何响应
- 3355没有变化除非自己重启或者重启加载
- 难道每次运维修改后,都需要重启?
相当于直接修改Github上的配置文件,配置不会改变,这个时候就存在了分布式配置的动态刷新问题
3、Config客户端之动态刷新
为了避免每次更新配置都要重启客户端微服务3355
引入actuator监控依赖
<!--web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后修改bootstrap.yml,暴露监控端点
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
在业务类中,添加 @RefreshScope
标签
@RestController
//实现刷新功能
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo(){
return configInfo;
}
}
然后让运维人员发送一个post请求
curl -X POST "http://localhost:3355/actuator/refresh"
然后就能够生效了,成功刷新了配置,避免了服务重启
这个方案存在问题:
- 假设有多个微服务客户端 3355/ 3366 / 3377
- 每个微服务都要执行一次post请求,手动刷新?
- 可否广播,一次通知,处处生效?
目前来说,暂时做不到这个,所以才用了下面的内容,即Spring Cloud Bus 消息总线
三、消息总线SpringCloudBUS
消息总线一般是配合SpringCloudConfig一起使用的
概述
分布式自动刷新配置功能,SpringCloudBus配合SpringCloudConfig使用可以实现配置的动态刷新
Bus支持两种消息代理:RabbitMQ和Kafka
SpringCloudBus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。
SpringCloudBus能管理和传播分布式系统的消息,就像一个分布式执行器,可用于广播状态更改,事件推送等,也可以当做微服务的通信通道。