1.1 从一次系统改造谈灰度
公司开办之初,为了能够快速实现公司的战略,就从市场上选购了一套系统,进行了外包方式的合作,这也是大多数公司创业的捷径。随着公司的快速发展,公司组建了自己的研发团队,对现有的系统进行重构变得尤为迫切。同样面临的问题是:领导对时间要求紧迫、研发对现有系统摸不透、做到数据的兼容性,基于这样的要求就必须做到系统上线采用灰度的方式,指定忠实用户进行线上测试、选取有特征的群体进行线上测试和基于流量切换的方式进行线上测试等。
在上面的需求推动下,本人对灰度进行了一次重新的构思。在之前的工作中也都涉及到灰度,当时觉得这都应该是大公司运维的事儿,现在想想这不但是大公司的事儿,更是一个快速发展中的公司应该重视的事儿,尤其是对于互联网公司。
互联网产品有一个特点,就是不停的升级,升级,再升级。一般采用敏捷开发的团队,基本上保持每周一次的发布频率,系统升级总是伴随着风险,新旧版本兼容的风险,用户使用习惯突然改变而造成用户流失的风险,系统down机的风险.....为了避免这些风险,很多产品都采用了灰度发布的策略,其主要思想就是把影响集中到一个点,然后再发散到一个面,出现意外情况后很容易就回退,即使影响也是可控的。
1.2 传统系统发布
在百度上搜索了一下:灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
在飞速发展的互联网公司,灰度其实就是根据设定的规则将请求路由到我们的灰度版本(灰度机器)上来。比如对于API来说,一般有如下几个需求:特定用户(比如测试帐号)、 特定的App(比如测试app或者合作App)、特定的模块、接口(只有某些接口需要灰度,这种一般是API Container的修改,拿一些不是很重要的API做灰度测试)、特定的机器(某些请求IP转发到灰度机)等。
在传统软件产品发布过程中(例如微软的Windows 7的发布过程中),一般都会经历Pre-Alpha、Alpha、Beta、Release candidate(RC)、RTM、General availability or General Acceptance (GA)等几个阶段(参考Software release life cycle)。可以看出传统软件的发布阶段是从公司内部->外部小范围测试>外部大范围测试->正式发布,涉及的用户数也是逐步放量的过程。
1.3 灰度发布能够解决的问题
我们公司是一个互联网公司,不过为了保障系统上线的可靠性,也是一样,每次系统的上线都是经过开发、site、test、bate、生产的多个过程。当程序员和测试人员信心满满的要将系统推到线上的时候,可能因为一个小小的配置导致系统的线上故障,风险不可预估。
每一次产品发布,交到用户手中的时候却不知道这次的产品设计是否能够给用户带来更好的体验,不能指定特殊人群,优先对新的产品进行线上的验证和体验。
基于如上的问题联想灰度可以解决的问题:
1、 在发布过程中降低上线风险
2、 降低影响范围,并且范围可控
3、 降低对测试的依赖,减少线下自测的数据构造成本
4、 特定的请求能够指向特定的服务器,方便集中监控日志,方便跟踪完整的调用链路
5、 方便系统流量切入
6、 方便回滚
7、 指定特定人群,方便系统回访,方便产品需求收集,完善产品功能,提升产品质量
8、 在无状态的情况下保障用户使用到的版本一致
9、 避免停服给用户带来坏的体验用
2 思考
要能解决上面提到的问题有多重方式,不同公司有不同的实现方式。作为一个开源的灰度系统就要 考虑到对业务无侵入,方便升级和配置。
有很多公司实现灰度是基于多部署一套灰度环境作为灰度发布的场景,这样在某些层面是可以达到灰度的手段,但是前端入口配置杂乱,不易于维护,同时不能保障线上系统的配置和灰度系统相同,环境也可能存在差别,存在上线的风险。
开发一套灰度系统就变得尤为重要,尤其是对于小公司,没有精力去做也就无法保障系统上线的平稳。本人也是出于这种冲动,写下了一套灰度系统,将其开源出来,希望能够为小公司提供一种解决方案,希望能够作为大公司灰度更好参考。
3 系统设计
本系管理统主要采用java技术开发,服务端主要用到了spring+springmvc+mybatis+dubbo,前端采用easyui;数据库采用mysql;灰度引擎当前采用java和lua两种技术开发。
项目代码:http://git.oschina.net/xiaoleiziemail/gray
3.1 设计目标
1、 能够解决上面提到的问题
2、 做到系统的灵活配置
3、 做到系统不牵涉业务
4、 做到对原有系统无侵入性
3.2 应有功能
3.3 整体设计
灰度系统主要分为管控和引擎两大块。管理用户通过管理端对灰度策略和白名单等进行管理,用户请求经过不同的灰度引擎进行智能路由。
4 管控平台
4.1 灰度管理
4.1.1 白名单分组
4.1.2 白名单管理
4.1.3 策略管理
4.1.4 应用管理
4.1.5 应用服务
4.1.6 应用灰度
4.1.7 服务灰度
4.2 日志监控
4.3 权限管理
5 灰度引擎
目前实现了两种接入方式的引擎,http接入采用lua开发,基于nginx进行灰度,dubbo接入方式采用java开发,选用灰度的负载均衡实现灰度。
5.1 Http接入
主要是针对Http入口的应用进行灰度,在应用前端配置nginx负载,在负载的过程中根据相应的策略进行灰度选择和请求转发。
http请求的入口都在nginx上,nginx会根据location的配置进行uri的选择。此时请求数据会判断当前应用是否已经开启灰度,再次判断是应用级别的灰度还是服务级别的灰度,然后根据管控平台配置的灰度策略进行灰度,当前支持白名单、小流量、正则表达式,后续会完善业务域、权重、ip段、地域等。
管控平台会调用引擎管理执行相应的指令,进行关闭、开启、更新策略和白名单数据等,每次nginx重新reload和重启时会从灰度管理系统调用接口读取配置应用的信息,加入缓存。
为了提升性能,应用的基本信息、灰度策略、白名单等数据缓存在nginx开辟的共享内存块中,nginx的每个worker进程都共享此数据,在引擎管理的操纵下进行缓存数据的更新。
5.2 Dubbo接入
根据规则在dubbo的入口处选择, dubbo-consumer实现不同的负载均衡,在负载的时候进行白名单校验和策略选择。系统对灰度管控平台非强制依赖,管控平台出现问题不影响系统正常运行。
1. 缓存负载策略
在系统启动的时候要根据系统配置拉取灰度策略,并且保存在内存中,定时获取最新的负载策略,需要提供及时触发的策略更新接口。
2. 白名单更新
在系统启动的时候要根据系统配置拉取白名单,并且保存在内存中,定时获取最新的白名单,需要提供及时触发的白名单更新接口。
3. 负载均衡引擎
在系统上线之前选择运行时使用的负载均衡引擎,可提供按照小流量、白名单等方式。
4. 系统配置
系统在上线前需要录入管控平台,并且完成相应的配置,在启动的时候作为唯一标识能够拉取相应的配置。
5. 监控和统计
系统在内存中缓存统计信息,定时上传管控平台,监控出现问题不影响系统正常使用(暂无实现)。
6 畅想未来
1、 丰富灰度策略,比如按照地域进行灰度等
2、 实现基于MQ、Schedule等多重接入方式的灰度
3、 实现用户数据的收集
4、 实现用户请求的链路监控
5、 提供运营和运维的开放式接口,提升运营手段,降低运营成本
6、 实现基于docker和灰度系统的全新测试环境