apollo灰度发布
# 一、灰度发布简介
灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题。
灰度发布就是让配置先在部分实例生效,如果效果理想全量发布到所有实例,如果效果不理想就可以放弃当前的“灰度发布配置”。
Apollo与灰度发布
- 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
- 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。
- 项目自有配置和namespace公有配置都可以实现灰度发布,但是二者是分开实现的
- 项目自有配置在所属项目配置管理界面操作,namespace公有配置在“创建namesapce”的项目管理进行操作
# 二、实战需求说明
为了切实的演示灰度发布,我给大家举一个我们经常会遇到的一个需求:日志输出级别的动态调整。 比如:aservice-sms应用启动了2个实例,我只想在其中一个实例上面将日志输出级别调整为WARN(默认INFO)。这样输出的日志内容更少,节省存储空间。待第一个实例的日志输出级别的WARN,观察之后没有其他问题,我们可以选择全量发布。
默认情况下,Spring Boot日志输出级别在apollo中是无法实现热更新的(也就是《apollo实例配置热更新》中讲的第一类配置),但是我们可以自己实现。实现的代码如下:
package com.zimug.dongbb.cloud.aservice.sms.config;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Set;
@Service
public class LoggerConfiguration {
private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class);
private static final String LOGGER_TAG = "logging.level.";
@Resource
private LoggingSystem loggingSystem;
@ApolloConfig
private Config config;
@ApolloConfigChangeListener
private void configChangeListter(ConfigChangeEvent changeEvent) {
refreshLoggingLevels();
}
@PostConstruct
private void refreshLoggingLevels() {
Set<String> keyNames = config.getPropertyNames();
for (String key : keyNames) {
if (containsIgnoreCase(key, LOGGER_TAG)) {
String strLevel = config.getProperty(key, "info");
LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
logger.info("{}:{}", key, strLevel);
}
}
}
private static boolean containsIgnoreCase(String str, String searchStr) {
if (str == null || searchStr == null) {
return false;
}
int len = searchStr.length();
int max = str.length() - len;
for (int i = 0; i <= max; i++) {
if (str.regionMatches(true, i, searchStr, 0, len)) {
return true;
}
}
return false;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 三、实验环境准备
以下是我的实验环境,大家可以按照我的实验环境自行模拟构建自己的实验环境
- 首先我们将aservice-sms打包上传到到192.168.161.4,192.168.161.5主机上
- 然后使用
nohup java -jar ./aservice-sms-1.0.jar -Denv=DEV &
命令启动,nohup就是不挂起的意思( no hang up),使用nohup启动的进程,默认会将该进程的日志输出到./nohup.out
文件中 - 使用
tail -f ./nohup.out
监控日志文件的实时输出(就像我们的IDEA的控制台输出一样)。方便我们查看apollo配置灰度发布的结果。
我们在apollo配置管理中心中,可以看到我们的两个实例都已经成功的读取了配置。到此,我们灰度发布的实验基础环境就完成了。
# 四、灰度发布实战
# 4.1.创建灰度
点击application右上角的灰度
按钮,创建“灰度发布”。
点击确定后,灰度版本就创建成功了,页面会自动切换到灰度版本
Tab.
# 4.2.灰度配置
在灰度版本
Tab中,可以"新增"灰度配置(主版本没有的配置项),也可以在主版本已有的配置项基础"修改"为会读配置。分别对应上图中的蓝色边框部分和黑色边框部分。在此我们新增灰度配置:logging.level.root=warn
# 4.3.配置灰度规则
切换到灰度规则
Tab,点击新增规则
按钮
在弹出框中灰度的IP
下拉框会默认展示当前使用配置的机器列表,选择我们要灰度的IP:192.168.161.4,点击完成
# 4.4.灰度发布
切换到配置
Tab,再次检查灰度的配置部分,如果没有问题,点击灰度发布
发布后,切换到灰度实例列表
Tab,就能看到192.168.161.4已经使用了灰度发布的配置项
# 五、需求实现效果说明
在192.168.161.5的主机上,我们一直可以看到如下的nohup.out输出日志:
但是在192.168.161.4的主机看不到上面的INFO级别的日志输出,因为我们通过设置灰度规则,指定了将192.168.161.4主机上的aservice-sms日志输出级别改为warn。warn的级别比INFO更高,所以在192.168.161.4看不到INFO级别的日志输出。
- 灰度发布:日志级别WARN只在192.168.161.4实例上发布,192.168.161.5我们没做发布
- 日志级别热更新:我们没有重启应用,应用的日志输出效果就发生了变化
# 六、放弃灰度与全量发布
如果我们在通过灰度发布的配置测试下来比较理想,符合预期,那么就可以操作全量发布
。
全量发布的效果是:
- 灰度版本的配置会合并回主版本
- 主版本的配置会自动进行一次发布
- 在全量发布页面,可以选择是否保留当前灰度版本,默认为不保留。
如果我们通过灰度发布的配置测试下来不理想或者不需要了,可以点击放弃灰度