- 业务需求
- 研发小故事
- 为什么要配置中心?
- 配置中心解决办法
- 现代需求
- 配置的定义和场景
- 基本概念
- 分类
- 应用 & 场景
- 开关驱动开发原理
- 基于主干的开发模式 TBD
- 优劣
- Apollo简介
- 功能亮点
- 简化架构
- 主界面
- Apollo核心概念
- 应用 application
- 环境 environment
- 集群 cluster
- 名字空间 namespace
- 配置项item
- 权限
- Apollo 快速起步
- Apollo架构设计之服务器端
- 架构视图1
- 架构视图2
- 领域模型
- 权限模型
- 实时推送设计
- ReleaseMessage实现
- Apollo架构设计之客户端
- Apollo架构设计之高可用和监控
- Apollo分布式部署指南
- Apollo Java客户端和多语言接入
- Spring Cloud Config 简介
- Apollo vs spring cloud config
- 开发FAQ
公司的业务开发也使用了apollo, 这里顺带着学一下
原作者宋顺
容器是不可变的
配置的定义和场景 基本概念
灰度发布: eg 20个实例, 逐个 让配置生效
应用配置: 在运行的时候根据生产运维的实际情况去调配
研发人员自主的蓝绿发布
功能降级
可以对普通用户和vip用户操作 访问权限
只有beta用户可以走新功能, 降低了功能上线的风险
开关驱动开发原理开关驱动开发的研发模式
M 运营
D 产品
E 开发
敏捷开发: 小步前进, 快速迭代
基于开关: 比敏捷开发更快更高效
merge痛点, 合并冲突非常多
Branch by Abstraction
- 先提取接口
- 逐渐流量指向新功能
将新功能隐藏在开关后面, 通过开关可以不用开分支
若开发到F回退到C
不需要删/改代码, 只需要改开关
提高灵活度
DEV 开发环境
FAT 功能测试环境
UAT 用户验收测试环境
PRO 生产环境
私有类型只有专属应用能获取
公共类型都可以获取
若是对公共类型不满意, 可以使用关联类型覆盖属性值
公有配置是所有app都可以用的, 没有app
参考
Apollo快速起步
客户端demo
package com.ctrip.framework.apollo.demo.api;
import com.google.common.base.Charsets;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SimpleApolloConfigDemo {
private static final Logger logger = LoggerFactory.getLogger(SimpleApolloConfigDemo.class);
private String DEFAULT_VALUE = "undefined";
private Config config;
public SimpleApolloConfigDemo() {
ConfigChangeListener changeListener = new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
logger.info("Changes for namespace {}", changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
logger.info("Change - key: {}, oldValue: {}, newValue: {}, changeType: {}",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType());
}
}
};
config = ConfigService.getAppConfig(); // 拿到apollo的配置
config.addChangeListener(changeListener); // 加载一个监听器, 配置有变更的话会实时通知config
}
private String getConfig(String key) {
String result = config.getProperty(key, DEFAULT_VALUE);
logger.info(String.format("Loading key : %s with value: %s", key, result));
return result;
}
public static void main(String[] args) throws IOException {
SimpleApolloConfigDemo apolloConfigDemo = new SimpleApolloConfigDemo();
System.out.println(
"Apollo Config Demo. Please input key to get the value. Input quit to exit.");
while (true) { // 一直循环获取用户的输入
System.out.print("> ");
String input = new BufferedReader(new InputStreamReader(System.in, Charsets.UTF_8)).readLine();
if (input == null || input.length() == 0) {
continue;
}
input = input.trim();
if (input.equalsIgnoreCase("quit")) {
System.exit(0);
}
apolloConfigDemo.getConfig(input); // 从config中读取input相应的value
}
}
}
client目录下的META-INFOapp.properties需要配置
app.id = SampleApp
需要与配置中心项目信息的AppId对应
核心模块:
ConfigService
AdminService
Portal
Client
Eureka, MetaServer, SLB (Software Load Balancer) 用于辅助服务发现用
帮助Client找到ConfigService, Portal找到AdminService
找到以后通过Client通过直连的方式连接ConfigService, Portal通过直连的方式连接AdminService
Software Load Balancer, 携程内部的Nginx
ConfigService , AdminService , Portal, Client 都是核心业务功能服务
Eureka, MetaServer 用作服务发现
使用MetaServer, 解决服务发现的问题, 拓展对 Java(Eureka), .Net, python等语言的支持
架构视图2客户端发现后台服务以后, 通过客户端软负载的方式:
客户端会拿到ConfigService的地址列表, 随机的选一个, 以某种策略去连后面的服务, 如果出现错误可以去重试其他的列表中的地址
对于用户来说, 通过公司的负载均衡器 Nginx 去访问 Portal, Portal也是多份实例部署, 通过 Nginx LB 做负载均衡
样例
依赖于git
实现动态配置相当复杂 SpringCloudBus RefreshScope
对动态配置支持弱
灰度发布: 多个客户端, 依次生效



