集群管理
在有些情况下,应用有需求对不同的集群做不同的配置,比如部署在A机房的应用连接的RocketMQ服务器地址和部署在B机房的应用连接的RocketMQ服务器地址不一样。另外在项目开发过程中,也可为不同的开发人员创建不同的集群来满足开发人员的自定义配置。
创建集群
之前的操作都是在默认集群里面,数据也是在默认集群里面
在新建的集群中,每一个的namespace都是没有数据的,还是需要自己去创建或关联
同步集群配置
选择需要同步的配置
读取集群配置
需要在环境的地方指定集群,
之前的配置信息如下:
-Dapp.id=apollo-quickstart -Denv=DEV -Ddev_meta=http://localhost:8080
指定集群后的配置
-Dapp.id=apollo-quickstart -Denv=DEV -Dapollo.cluster=SHAJQ -Ddev_meta=http://localhost:8080
修改代码:
public class GetConfigTest {
public static void main(String[] args) {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Config appConfig = ConfigService.getAppConfig();
//读取指定的namespace下的配置信息
Config config = ConfigService.getConfig("spring-rocketmq");
//获取配置信息,第一个参数:配置的key,第二个参数:默认值
String value = config.getProperty("rocketmq.name-server", null);
System.out.printf("现在:%s, sms.enable: %s%n", new Date().toString(),value);
}
}
}
配置发布原理
在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。设计实现如下图:
主要过程描述:
-
用户在Portal操作配置发布
-
Portal调用Admin Service的接口操作发布
-
Admin Service发布配置后,发送ReleaseMessage给各个Config Service
-
Config Service收到ReleaseMessage后,通知对应的客户端
发送ReleaseMessage的实现
Admin Service在配置发布后,需要通知所有的Config Service有配置发布,从而Config Service可以通知对应的客户端来拉取最新的配置。
从概念上来看,这是一个典型的消息使用场景,Admin Service作为producer (生产者)发出消息,各个ConfigService作为consumer(消费者)消费消息。通过一个消息队列组件(Message Queue )就能很好的实现AdminService和Config Service的解耦。
在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。
具体实现方式如下:
- Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的Appld+Cluster+Namespace
- Config Service有一个线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录
- Config Service如果发现有新的消息记录,那么就会通知到所有的消息监听器,然后调用消息监听类的handleMessage方法:NotificationControllerV2
- NotificationControllerV2得到配置发布的Appld+Cluster+Namespace后,会通知对应的客户端
Config Service通知客户端
实现方式如下:
- 客户端会发起一个Http请求到Config Service的notifications/v2接口NotificationControllerV2
- NotificationControllerV2.不会立即返回结果,而是把请求挂起。考虑到会有数万客户端向服务端发起长连,因此在服务端使用了async servlet(Spring DeferredResult,异步的servlet方式)来服务HttpLong Polling请求。
- 如果在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端。
- 如果有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的setResult方法,传入有配置变化的namespace信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的namespace后,会立即请求Config Service获取该namespace的最新配置。
客户端读取设计
除了之前介绍的客户端和服务端保持一个长连接,从而能第一时间获得配置更新的推送外,客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
- 这是一个备用机制,为了防止推送机制失效导致配置不更新
- 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304- NotModified
- 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property:apollo.refreshInterval来覆盖,单位为分钟
部署方案
在企业中常用的部署方案为:
Apollo-adminservice和Apollo-configservice两个服务分别在线上环境(pro,有几个环境就需要配置多少个adminservice + configservice
),
仿真环境(uat)和开发环境(dev)各部署一套,
Apollo-portal做为管理端只部署一套,统一管理上述三套环境
。
总结:生产环境下面,有生产环境、测试环境等待,每一个环境都需要部署一个admin和config,portal是共有的一套环境
灰度发布
定义:灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing。
即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。
apollo实现的功能:
- 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
- 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。