引入
小D是研发工程师,某天产品说要开发一个双十一商品促销功能。由于产品无法预估促销商品的需求量,于是拍脑袋说,每个用户限购10个!
小D代码:
//产品需求每个用户限购10个商品
privatestaticfinalintMAX_QTY_PER_USER=10;
publicbooleanpurchase(intquality) {i
if(quality>MAx_QTY_PER_USER) {
thrownewIllegalArgumentException(
String.format("每个用户限购%d个商品",MAX_QTY_PER_USER));
}
//商品购买逻辑
returntrue;
}
促销当日中午,销售火爆出乎产品预料,产品匆忙跑到小D处,要求赶紧改成每人限购2个!
小D只好放弃午饭,改代码、回归测试、上线,整整花了1个多小时才搞定。
小S是研发工程师,某天产品说要开发一个双十一商品促销功能。由于产品无法预估促销商品的需求量,于是拍脑袋说,每个用户限购10个!
小S吸取了小D的教训,直接把配置写在了集中式配置中心里头:
促销当日中午,销售火爆出乎产品预料,产品匆忙跑到小S处,要求赶紧改成每人限购2个!
小S花了10秒钟,改了配置就好了!!!
传统应用配置的问题
主要采用本地文件静态配置:本地静态配置导致在运行时无法动态修改
配置散乱格式不标准:有的用xml格式,有的用properties,有的存DB
易引发生产事故:发布的时候容易将非生产的配置带到生产上,引发事故
配置修改麻烦,周期长:当部署的服务器很多时,修改配置费时费力
配置信息缺少安全审计和版本控制功能:事后无法追溯,谁改的?改了什么?什么时候改的?当出现问题无法及时回滚
现代交付需求(云原生:包含两个趋势)
微服务:服务微化
容器化:现代的交付方式对配置有新的要求
开关驱动开发
现代配置核心需求
交付件和配置分离
抽象标准化:配置格式用户不用担心,配置中心提供接口,客户对接
集中式:统一的配置中心,不需要根据业务团队单独搞一套
高可用
实时性
治理:权限审计、权限控制,谁在什么时间点干了什么事,支持回退
配置中心
配置的定义与场景
配置定义:
可独立于程序的可配变量
同一份程序在不同配置下会有不同行为
连接字符串,应用配置,业务配置
配置形态
程序内部硬编码
配置文件
环境变量
启动参数
基于数据库
配置治理
权限控制和审计
不同环境、集群配置管理。
框架类组件配置管理
灰度发布
分类
静态配置:
环境变量:数据库、中间件、其他服务的连接字符串
安全配置:用户名、密码、令牌、许可证等
动态配置
应用配置:请求超时,线程池,队列、缓存,数据库连接池的容量、日志级别、限流熔断阈值、黑白名单
功能开关:蓝绿发布,灰度开关,降级开关,HA高可用开关,DB迁移
业务配置:促销规则,贷款额度,利率等业务参数,A/B测试
蓝绿发布:
没有配置中心时,两个版本需要依赖运维帮助我们配置路由,(效率较低,需要协调资源,想要切换也比较麻烦,需要开发和运维协调)
可在代码中埋一个开关,通过配置中心的配合,做到蓝绿版本的切换,加入蓝色版本上线效果不佳,再次切换也比较方便。
功能降级:
当在遇到促销火爆、非法攻击使流量突增时,可以在应用层代码中埋一个开关,去做限流和降级。还可以针对用户去做不同处理,如vip用户继续访问,普通用户给一个友好提示进行限流降级。
数据迁移:
迁移过程渐进的方式,逐步的完成,这个过程的10%的读写、100%的读写,就需要配置中心去调节,尽可能小的去进行迁移
A/B测试:
在配置中心配合下,完成新功能的上线,很好的降低直接上线的风险。
概述
随着程序功能的日益复杂,程序的配置也日益增多,各种参数的配置、功能的开关、服务器的地址。我们对程序的期望值也越来越高,配置修改完要实时生效、灰度发布、分环境、分集群管理、完善的权限审核机制等,在这样的大环境下,传统的key-value配置、或者数据库的配置无法满足对配置管理的需求。
Apollo采用微服务架构,设计轻巧,功能完善,提供统一界面管理应用在不同环境不同集群的配置,用户在Apollo修改完配置后可以实时生效,也支持版本的概念,支持回滚,支持灰度发布,支持完善的权限审核、发布审核、操作审计等。
配置中心属于基础服务,对可用性要求较高,所以Apollo对外部依赖要尽可能的少,目前唯一的外部依赖是数据库,不需要任何组件,部署比较简单,客户端和服务端有多级缓存,数据库挂了也不会有很大的影响。
简化架构
配置管理员去配置中心修改发布配置,可以实时通知到应用客户端,客户端也可通过拉取的方式进行获取配置中心的最新配置。
核心概念
应用:即使用配置的应用,有一个唯一的appId
环境:DEV、FAT、UAT、PRO等。一个应用在多个环境下都有部署,Apollo可以管理多套环境。server.properties中注明环境
集群:一个应用下不同实例的分组。对不同的cluster,可以有不同的配置。比如:kafka地址针对上海机房和成都机房可以有不一样的配置
名字空间:一个应用下不同的配置分组,例如:数据库配置、框架配置、元数据配置可以建不同的分组管理配置。private、public、关联继承类型。
private:只能被所属应用类型获取。
public:必须全局唯一;主要是一些共有场景,例如部门级别、小组级别、中间件客户端的共享配置。(**)
关联继承:私有继承共有并有覆盖,或者可以定制公共组件的配置场景
配置项:表示可以配置的项,支持properties、json、xml格式。定位方式分为:
私有配置:env+app+cluster+namespace+item_key
共有配置:env+cluster+namespace+item_key
权限
系统管理员:拥有所有的权限
创建者:可以代为创建项目,责任人是默认的项目管理员,一般创建者=责任人
项目管理员:可以创建Namespace,集群管理项目和Namespace权限
编辑权限:只能编辑不能发布
发布权限:只能发布不能编辑
查看,普通用户:可以搜索查看所有项目配置,但不能做相关操作
快速入门
准备:
快速启动安装包下载地址:https://github.com/nobodyiam/apollo-build-scripts。下载之后进行解压
初始化数据库:
Apollo 服务端一共需要两个数据库:ApolloPortalDB 和 ApolloConfigDB。数据库、表的创建和样例数据的 sql 文件都在快速启动安装包的 sql 目录中,只需要导入数据库即可。
数据库连接信息在 demo.sh 中,我们需要把对应的数据库连接信息修改成我们自己安装的地址,这样 Apollo 才能正常启动。
启动:
./demo.shstart
发现http://localhost:8070 now!就可了。
创建用户:
进入用户管理界面:
http://{portal地址}/user-manage.html
创建项目:
增加新配置:增加、确定发布
修改应用配置:为当前应用
~/client/METE-INF/app.properties
客户端访问:
./dome.sh client
架构设计
服务端
模块介绍:
config service(服务Apollo客户端)
配置获取接口
配置推送接口
admin service(服务Portal)
配置管理接口
配置修改、发布接口
meta server
Portal通过域名访问Meta Server获取Admin Service服务列表
Client通过域名访问Meta Server获取Config Service服务列表相当于一个Eureka Proxy
逻辑角色,和Config Service住在一起部署
Eureka
服务注册发现
config/admin service注册并报心跳
和config service一起部署
Portal
配置管理界面
通过meta server获取admin service服务列表
客户端软负载
client
应用获取配置、实时更新
通过Meta server获取config service服务列表
客户端软负载
config service服务于client客户端,client通过config service获取配置,config service也可以实时推送 配置给client
admin service服务于portal管理端,portal通过调用admin service进行管理 config service和admin service共享一个configdb
portal有单独的db
config service和admin service一般是以服务、集群的方式进行部署此时就涉及到服务发现注册的问 题
eureka config service和admin service会在eureka中注册并定期报心跳
meta aserver 为了支持多语言,meta server对eureka进行包装,简化client和portal去eureka找服务 的过程,直接找meta server就好
NginxLB client和portal在寻找meta server(meta server也是集群部署)时,通过NginxLB负载均衡器
综上:引入的eureka 、meta aserver、NginxLB解决的就是服务发现的问题简化架
领域模型
一个(app)应用有多个集群(cluster),一个集群下有多个名字空间(namespace),一个名字空间下有若干个配置项(item),编辑提交(commit),和发布数据(release)。
AppNameSpace:(app)应用的元数据,如:应用有哪些名字空间、共有还是私有等,而名字空间(namespace)是指集群下具体的namespace实例。
Audit:用户任何操作,都会被审计,后继可做审计查询
权限模型
用户有角色、角色有权限。
Apollo支持第三方接入,需要申请token,分布角色,并做审计
实时推送设计
客户端
推拉结合
保持一个长连接,配置实时推送
定期拉配置(fallback)
配置缓存在内存
本地再缓存一份
C: \opt\data\appId\config-cache
应用程序
通过Apollo客户端获取最新配置
订阅配置更新通知
高可用
结合架构图
SpringCloudConfig vs Apollo
spring cloud config
spring cloud config是基于应用(application)、环境(profile:dev/test/prod)、版本(label)3个维度的配置管理
优势:
配置存储通过Git支持
spring无缝集成
涉及简单轻量
不足:
动态配置能力弱
治理能力弱(审计、权限控制)
不算严格的企业级(适用小型项目)
接口样例:
接口url:/{application}/{profile}/{label}
例如:http://localhost:9000/appfoo/production/master
简化架构
动态配置的实现:(较为复杂)
对比
结论:Apollo是企业生产级配置中心,适用范围更广
常见问题
cluster是什么?
一个应用不同实例的分组,比如典型的多机房部署按数据中心分集群。
Namespace是什么?
一个应用下不同配置的分组,例如:应用配置application,中间件配置framework,数据库配置 database
多个应用想要用同一个配置,如何做到?
使用公有的Namespace
客户端访问配置是否有权限,是否支持配置加密?
Apollo client获取配置没有权限管控,配置加密需要应用层自己实现
为什么不能进行编辑发布操作?
编辑和发布需要管理员授权,即使是管理员自己也需要自己给自己授权