灰度发布--转载

互联网产品灰度发布

 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/boonya/article/details/51537674

关于2016年5月15日,DevOps成都站|架构与运维峰会活动总结

1. 前言 2

2. 灰度发布定义 5

3. 灰度发布作用 5

4. 灰度发布步骤 5

5. 灰度发布测试方法 6

6. 灰度发布引擎 6

7. 灰度发布常见问题 8

7.1. 以偏概全 8

7.1.1. 问题特征: 8

7.1.2. 解决方案: 8

7.2. 知识的诅咒 9

7.2.1. 问题特征: 9

7.2.2. 解决方案: 9

7.3. 发布没有回头路可走 9

7.3.1. 问题特征: 9

7.3.2. 解决方案: 9

7.4. 用户参与度不够 10

7.4.1. 问题特征: 10

7.4.2. 解决方案: 10

8. 让产品具备灰度发布能力 10

8.1. 灰度机制的七个维度 10

8.1.1. 需求度 10

8.1.2. 速度 10

8.1.3. 灵活度 10

8.1.4. 冗余度 11

8.1.5. 开放协作度 11

8.1.6. 进化度 11

8.1.7. 创新度 11

8.2. 灰度发布的策略要素 11

8.2.1. 易于发布到云平台 11

8.2.2. 设置用户标识策略 12

8.2.3. 目标用户选取策略 12

8.2.4. 提供数据反馈入口 12

8.2.5. 新版本回滚策略 12

8.2.6. 新版本公关运营支持 13

8.3. 灰度发布的方案 13

8.3.1. 方案一:代码逻辑控制 13

8.3.2. 方案二:Alibaba预发机制 14

8.3.3. 方案三:SET部署 14

8.3.3.1. 按照业务隔离部署 14

8.3.3.2. 按照用户隔离部署 15

8.3.4. 方案四:动态路由 16

9. 采用灰度发布的案例 16

9.1. 谷歌Gmail Labs 16

9.2. 腾讯QZone 17

9.3. 微信wechat 17

9.4. Ucloud高可用架构实践 20

10. 参考资料 26

1. 前言

 互联网产品有一个特点,就是不停的升级,升级,再升级。一般采用敏捷开发的团队,基本上保持每周一次的发布频率,系统升级总是伴随着风险,新旧版本兼容的风险,用户使用习惯突然改变而造成用户流失的风险,系统down机的风险.....为了避免这些风险,很多产品都采用了灰度发布的策略,其主要思想就是把影响集中到一个点,然后再发散到一个面,出现意外情况后很容易就回退。

很长时间,我们都一直在改进搜索引擎的排序算法,尽量让最好的商品出现在 搜索结果的第一屏。我们尝试了很多种算法,不断调整各个排序因子所占的比重。但是我们无法确信我们的排序结果能满足所有用户的需求。所以我们采用了灰度发 布,选取几个一级商品类目,在其中应用不同的排序算法,比如在女装类目中,我们把卖家信用所占的比率调整到60%,在珠宝类目中,我们把销售量所占的比率 调整到60%.. 然后发布出去,收集用户反馈,最终选择一种大部分人认为好的算法。

     在传统软件产品发布过程中(例如微软的Windows 7的发布过程中),一般都会经历Pre-Alpha、Alpha、Beta、Release candidate(RC)、RTM、General availability or General Acceptance (GA)等几个阶段(参考Software release life cycle)。可以看出传统软件的发布阶段是从公司内部->外部小范围测试>外部大范围测试->正式发布,涉及的用户数也是逐步放量的过程。

   在互联网产品的发布过程中也较多采用此种发布方式:产品的发布过程不是一蹴而就,而是逐步扩大使用用户的范围,从公司内部用户->忠诚度较高的种子 用户->更大范围的活跃用户->所有用户。在此过程中,产品团队根据用户的反馈及时完善产品相关功能。此种发布方式,按照中国特色的叫法被冠 以”灰度发布“、”灰度放量“、”分流发布“。

  关于“灰度发布”叫法的来源无从考察。只不过按照中国传统哲学的说法来看,很符合中国人中庸的思维模式:自然界所有的事物总是以对称、互补、和谐的形式存 在,例如黑与白、阴与阳、正与负、福与祸。在二元对立的元素间存在相互过渡的阶段,所谓”祸兮福所倚,福兮祸所伏“。具体到黑与白,在非黑即白中间还有中 间色——灰色。于是出现了很多关于灰色的说法:灰盒测试,灰色管理(极力推荐 任正非:管理的灰度),灰色收入,灰色地带等等。因此对于灰度发布实际上就是从不发布,然后逐渐过渡到正式发布的一个过程。

2. 灰度发布定义

灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

3. 灰度发布作用

a.及早获得用户的意见反馈,完善产品功能,提升产品质量

b.让用户参与产品测试,加强与用户互动

c.降低产品升级所影响的用户范围

d.规避一定的发布风险

e.避免停服发布给用户带来不便

f.具有容灾能力

4. 灰度发布步骤

  1)、定义目标

  2)、选定策略:包括用户规模、发布频率、功能覆盖度、回滚策略、运营策略、新旧系统部署策略等

  3)、筛选用户:包括用户特征、用户数量、用户常用功能、用户范围等

  4)、部署系统:部署新系统、部署用户行为分析系统(web analytics)、设定分流规则、运营数据分析、分流规则微调

  5)、发布总结:用户行为分析报告、用户问卷调查、社会化媒体意见收集、形成产品功能改进列表

  6)、产品完善

  7)、新一轮灰度发布或完整发布

5. 灰度发布测试方法

     灰度发布于互联网公司常用A/B测试似乎比较类似,老外似乎并没有所谓的灰度发布的概念。按照wikipedia中对A/B测试的定义,A/B测试又叫:A/B/N Testing、Multivariate Testing,因此本质上灰度测试可以算作A/B测试的一种特例。只不过为了术语上不至于等同搞混淆,谈谈自己理解的两者的差异。

    灰度发布是对某一产品的发布逐步扩大使用群体范围,也叫灰度放量

    A/B测试重点是在几种方案中选择最优方案

   关于A/B测试可以参考这篇文章:A/B测试终极指南

6. 灰度发布引擎

     对于一般的小系统并不需要单独的灰度发布引擎,可以参考A/B测试中做法,在页面javascript或服务器端实现分流的规则即可。但对于大型的互联网应用而言,单独的用于管理用户分流的发布引擎就很有必要了。“钱掌柜”分流发布模式 提到了原来阿里软件所使用的灰度发布引擎,设计思路具有普遍性,可以供参考

下面是一个灰度发布的架构示意图:

7. 灰度发布常见问题

7.1. 以偏概全

7.1.1. 问题特征:

a选择的样本不具有代表性;

b样本具有代表性,但选择样本用户使用习惯并没有涵盖所有核心功能

7.1.2. 解决方案:

样本选择要多样化,样本的组合涵盖大部分核心功能

7.2. 知识的诅咒

“知识的诅咒”的说法来自《粘住》中实验,具体可以自己搜索一下。我们自己对于自己开发的产品极为熟悉,于是乎想当然认为用户也应当能够理解产品的设计思路、产品的功能使用。

7.2.1. 问题特征:

a结果没有量化手段;

b只依赖于用户问卷调查;

c没有web analytics系统;

d运营数据不全面,只有核心业务指标(例如交易量),没有用户体验指标

e对结果分析,只选择对发布有利的信息,对其他视而不见

7.2.2. 解决方案:

a产品设计考虑产品量化指标

b结果分析依据量化指标而不是感觉

7.3. 发布没有回头路可走

7.3.1. 问题特征:

a新旧系统用户使用习惯差异太大,没有兼容原有功能

b新旧系统由于功能差异太大,无法并行运行,只能强制升级

c新系统只是实现了旧系统部分功能,用户要完整使用所有功能,要在 在新旧系统切换

d新旧系统数据库数据结构差异太大,无法并行运行

7.3.2. 解决方案:

    前期产品策划重点考虑这些问题,包括:回滚方案、 新旧系统兼容方案、用户体验的一致性、用户使用习惯的延续性、新旧系统数据模型兼容性

7.4. 用户参与度不够

7.4.1. 问题特征:

a指望用户自己去挖掘所有功能。对于一个产品,大部分用户经常只使用部分功能,用户大部分也很懒惰,不会主动去挖掘产品功能

b互动渠道单一

c陷入“知识的诅咒”,不尊重参与用户意见

7.4.2. 解决方案:

a善待吃螃蟹的样本用户,包括给予参与测试的用户小奖励(例如MS给参与Win7测试用户正版License)、给用户冠以title

b通过邮件、论坛、社区、Blog、Twitter等新媒体与用户形成互动

c提供产品功能向导。在hotmail最近的升级后的功能tip,gmail的tip都有类似的产品功能导向。在产品中会提示类似于:你知道吗,xx还提供xx功能,通过它你可以xx 。

8. 让产品具备灰度发布能力

8.1. 灰度机制的七个维度

8.1.1. 需求度

用户需求是产品核心,产品对需求的体现程度,就是企业被生态所需要的程度;

8.1.2. 速度

快速实现单点突破,角度、锐度尤其是速度,是产品在生态中存在发展的根本;

8.1.3. 灵活度

敏捷企业、快速迭代产品的关键是主动变化,主动变化比应变能力更重要;

8.1.4. 冗余度

容忍失败,允许适度浪费,鼓励内部竞争内部试错,不尝试失败就没有成功;

8.1.5. 开放协作度

最大程度地扩展协作,互联网很多恶性竞争都可以转向协作型创新;

8.1.6. 进化度

构建生物型组织,让企业组织本身在无控过程中拥有自进化、自组织能力;

8.1.7. 创新度

创新并非刻意为之,而是充满可能性、多样性的生物型组织的必然产物。

8.2. 灰度发布的策略要素

8.2.1. 易于发布到云平台

    一般采用灰度发布都是具有自主产品的平台模式发布,而不是在客户服务器端进行发布,具备自主研发产品和有一定硬件部署能力的企业可以考虑灰度发布。

灰度发布一般是基于云的需要,如负载均衡,用户隔离等机制。如大型的电商网站等都是采用的分布式部署方式,利用负载均衡实现服务器分发,将用户访问分配到不同的地区服务器访问,确保用户访问效率,提升用户体验。

之所以强调易于发布,就是公司要具备自己可操作的服务器设备(云服务设备),这样可以实现在用户不知情的情况下实现灰度发布。即,在用户无感知的情况下实现最优配置的测试部署,提升产品质量,实现产品快速迭代——频繁发布,实现具有意义的‘实时发布’策略。

注:需要开通云服务模式(有一定硬件和经济实力的公司可以考虑)。

8.2.2. 设置用户标识策略

用于区分用户,辅助数据统计,保证灰度发布过程中用户体验的连贯性(避免用户在新旧版本中跳变,匿名Web应用比较容易有这个问题)。匿名Web应用可采用IP、Cookie等,需登录的应用可直接采用应用的帐号体系。

8.2.3. 目标用户选取策略

即选取哪些用户先行体验新版本,是强制升级还是让用户自主选择等。可考虑的因素很多,包括但不限于地理位置、用户终端特性(如分辨率、性能)、用户自身特点(性别、年龄、忠诚度等)。对于细微修改(如文案、少量控件位置调整)可直接强制升级,对于类似新浪微博改版这样的大型升级,应让用户自主选择,最好能够提供让用户自主回滚至旧版本的渠道。

对于客户端应用,可以考虑类似Chrome的多channel升级策略,让用户自主选择采用stable、beta、unstable channel的版本。在用户有明确预期的情况下自行承担试用风险。

8.2.4. 提供数据反馈入口

     用户数据反馈:在得到用户允许的前提下,收集用户的使用新版本应用的情况。如客户端性能、客户端稳定性、使用次数、使用频率等。用于与旧版本进行对比,决策后续是继续扩大新版本投放范围还是回滚。

     服务端数据反馈:新版本服务端性能、服务端稳定性等,作用与用户数据反馈类似。

8.2.5. 新版本回滚策略

当新版本灰度发布表现不佳时,应回滚至旧版本。对于纯粹的Web应用而言,回滚相对简单。主要难点在于用户数据的无缝切换。对于客户端应用,如果期待用户自行卸载新版本另行安装旧版本,成本和流失率都太高。可以考虑通过快速另行发布新版本,利用升级来“回滚”,覆盖上次灰度发布的修改。

对于移动客户端,新版本发布成本较高,需要Appstore、Market审核。本人没有移动客户端产品的经验,不太确定移动客户端产品如何处理灰度发布及回滚。但尽量将客户端打造成Web App,会更有利于升级和回滚。(不过苹果对纯Web App类的App有较强的限制,好像已经不允许在Appstore上发布这类应用了?)

8.2.6. 新版本公关运营支持

对于改版级别的大型升级,需要配合公关运营支持,用于及时处理用户在微博、博客等渠道给出的“显式反馈”。对比通过隐式数据反馈得到的结论后,综合考虑应对策略。

8.3. 灰度发布的方案

灰度发布一般有三种方式 nginx+lua,nginx根据cookie分流,nginx 根据权重来分配:

     nginx+lua根据来访者ip地址区分,由于公司出口是一个ip地址,会出现访问网站要么都是老版,要么都是新版,采用这种方式并不适合nginx 根据权重来分配,实现很简单,也可以尝试nginx根据cookie分流,灰度发布基于用户才更合理。

Nginx+lua配置可以参考如下文章进行实践:

利用nginx+lua+memcache实现灰度发布

Nginx+Lua+Redis实例

nginx灰度方案---基于ip或者基于cookies

8.3.1. 方案一:代码逻辑控制

实现:

在代码中埋开关,做if-else判断,对于需要灰度的机器,设置开关为on,否则为off。每次版本发布都是有两个版本。

优点

· 快速回滚,不需要重新发布和重启系统。

缺点

· 对代码有倾入性。

· 分支逻辑,带来复杂性。

这种方式笔者曾经应用过,就是在阿里的时候把商品的数据库从Oracle切换到MySql,使用了一个状态变量进行控制。从而打到平滑迁移的效果。

8.3.2. 方案二:Alibaba预发机制

    其实这个不是真正意义上的灰度。因为这个预先发布机器是内部IP,没有对外服务的。需要绑定域名进行验证。但是数据是完全的线上。所以本质上是灰度 某些特定用户(可以访问灰度机器的用户,内部测试用户)的一种简单做法。其实API这边也有类似的做法,就是我们的Gamma环境,而且我们还提供了 Gamma机器的域名,方便外部合作用户配合测试。

优点

· 简单

缺点

· 浪费一台机器(这个可以预先发布完成之后投入正式环境,预发布的时候从nginx摘除,不过需要运维支持。)

· 不够灵活

· 只能针对接入层机器,IDL服务灰度需要另外考虑。

8.3.3. 方案三:SET部署

8.3.3.1. 按照业务隔离部署

    比如现在API Container的做法,部署的粒度可以到API级别,前端根据nginx进行转发。比如:

· 微购物 API Container: api.weigou.qq.com

· 拍拍 API Container:api.paipai.com

· 易迅 API Container: api.yixun.com

· 网购 API Container:api.buy.qq.com

    上面是大业务级别的隔离部署。还可以进一步细化到模块级别,比如虚拟服务电商的API,是挂在拍拍下面的一个子业务模块,但是由于他们接入微信之 后,访问量大增,为了避免影响拍拍其他业务,也为了避免受其他业务影响,API这里是给他们单独部署了两台机器,nginx配置一下就可以将针对虚拟的 API访问引流过来了:

虚拟API Container:http://api.paipai.com/v2/virbiz

这样,我们在发布一个版本的时候,可以先选择业务量最小的易迅进行发布,观察没有问题再全量其他平台。

8.3.3.2. 按照用户隔离部署

    这个对于开放平台来说不是很适合,不过对于SNS这种应用场景就很合适了。比如QQ系统,按照用户号码段分为若干个set,每个set包含连续1亿 个号码的用户。假设现在最新的QQ号码接近10亿,则总共有10个set(Set 1到Set 10)。这样每次可以选择其中一个SET进行发布,而且高位QQ往往是不是很重要的用户,所以会先发布SET10。

优点

· 隔离部署,各个业务线影响最小。自动支持灰度发布。

缺点

· 灰度的粒度取决于隔离部署的粒度,一般会偏大。

· 相对于集中部署比较浪费机器。

· 各个业务线版本可能不一致,不利于统一管理。

· 有一定的实现和部署成本

8.3.4. 方案四:动态路由

   采用一个可以灵活配置的灰度策略,影响Load Balance的行为,让其根据灰度策略,返回灰度服务的IP和端口。

适合与后台IDL的服务灰度。

优点

· 灵活,可控。

缺点

· 现在的配置中心和L5本身没有考虑指定路由策略,且不具有扩展性,需要在其外边开发。

· API的元数据来源比较分散,目前 API和IDL元数据,API等级和频率限制 分布在不同的数据源,现在需要增加一个 灰度路由 数据源。

A公司的灰度发布方案

为什么需要灰度发布?

我们的产品是个比较典型的互联网产品,产品升级采用“小步快跑”的方式,一般采用保持每周或每两周一次的发布频率,同时,每周会有数次bug上线。系统上线总是伴随着风险,系统重大bug的风险,新旧版本兼容的风险,用户使用习惯突然改变而造成用户流失的风险等等,因为这些风险的存在,很多次上线都是通宵达旦、小心翼翼,RD和QA都搞提很疲惫。为了不再如此疲惫,同时避免重大事故的发生,我们决定采用灰度发布的策略,其主要思想就是化大为小,逐渐发布,将风险引起的影响控制在最小范围。

如何进行灰度发布?

1, 首先,我们将系统分成两个集群,集群A和集群B,每个集群有一个nginx,在两个集群之上,有一个大的集群C,也有一个nginx。 

2, 在发布时,挑选在线用户比较小的时间点(如深夜),将小的集群B下线 

3, 将在PL环境测试通过的程序包部署到下线的小集群B,使用独立的账套在线进行关键流程的测试(以避免污染真实用户的线上数据)。 

4, 小集群测试通过之后,将小集群B上线,即,将小集群的nginx挂到大集群C的nginx下,上线试运行。 

5-1,如果新上线的小集群B运行稳定,则将新程序包发到集群A,从而完成整个集群的发布。 

5-2,如果新上线的小集群B有重大bug,则进行回滚。

以上步骤看起来很简单,但在实际落地过程中需要注意以下问题: 

1,集群A与B在应用层完全隔离,dubbo注册中心zk与mq是非共享的,但在数据层是共享的。即db,redis,mongodb,redis这些资源是由集群A&B共享的。因此,数据的schema对于新旧版本需要兼容。 

2,以上方案中,新旧版本是并行的,用户请求被随机分配到新旧版本的两个集群中。如果需要限定只有特定的用户才可以访问新系统(一般是铁粉用户),则需要增加路由规则。 

对于简单的路由规则,可以通过nginx+lua脚本的方式实现, 可参考: 

https://pingan.im/201503/nginx-lua-redis 

对于复杂路由规则相关的方案请参考: 

http://blog.csdn.net/hunter_1990s/article/details/43733349

B公司的灰度发布系统方案

1 背景与解决思路

做灰度发布,主要有两个大的方向

1.    在代码中做。一套线上环境,代码中做开关,对于不同的用户走不同的逻辑

2.    在接入层做。多套(隔离的)线上环境,接入层针对不同用户转发到不同的环境中

来分别看下这两种方案的优缺点

方案 优点 缺点
在代码中做 灵活,粒度细;一套代码(环境)运维成本低 灰度逻辑侵入代码
在接入层做 无需(少)侵入代码;风险小 多套线上环境,运维成本高

脱离具体的应用场景谈解决方案都是耍流氓。具体到我们的业务场景:

1.    对线上的质量要求高,目前无单测,QA黑盒测试,无自动化

2.    变更周期长(可接受),单次迭代功能点多

3.    流量低峰期在22点后,整体回归时间长,且存在漏测情况

可以看到我们要做灰度发布的主要诉求是保证线上的质量,尽量降低因迭代带来的服务问题。而非要针对于不同的用户做AB Test。考虑到如果灰度的方案涉及到修改代码,则可能引入其他不确定的风险,在此,我们采用第二种,也就是在接入层做分流的策略。

2 具体实现方案

2.1 接入层 -> Web层

接入层采用nginx,可以基于IP或cookie的方式进行分流,由于我们是商业ERP系统,有用户登录的逻辑,自然选择基于cookie的策略。

就基于cookie的分流策略而言,又有两种实现方案

1.    nginx维护Cookie名单文件,每来一个请求看Cookie是否在名单中,做不同的转发

2.    nginx不维护Cookie名单文件,根据Cookie的特征进行转发

第一种方案的缺点显而易见,每次请求判断是否是灰度用户时间复杂度为O(N);且变更名单,需要操作接入层服务。我们采用第二种方案,具体的实现策略

1.    业务中维护白名单文件(存放在数据库中)

2.    在登陆时,如果用户在名单中则给用set特定标识的Cookie;退出或Session过期后Cookie失效

3.    nginx匹配特定Cookie,做转发

这样,调整灰度的范围,只需要操作数据库即可,无需重启服务。

2.2 Web层 -> 核心层模块

目前两层模块之间的解耦方式是通过Zookeeper,对这部分的灰度发布的实现,是通过caller, callee约定一个固定的节点名称(可以把具体的版本号写进去)来实现。

3 运维上的升级

3.1 维护灰度的机器

我们采用${index}.${platform}.${module}来管理模块和机器的对应关系,多了一个灰度的机器,在${platform}中增加一个stage平台名,代表实验环境。

实验环境也属于线上环境,需要增加对应的监控。

全流量的机器不包含实验环境的机器,独立部署,转全后全流量的流量也不会落到stage机器上(nginx的upstream.conf文件不用动)

3.2 建立灰度编译打包、部署任务

全流量的编译打包,和灰度的打出来的包,是一样的,版本号也一样。

只在灰度部署的任务中,自动更新注册节点名称。

由于要固定caller, callee的ZK节点名称,所以,强制在灰度部署任务中,增加一个stage的标记逻辑。

3.3 nginx的转发逻辑

增加对于带cookie的请求转发

location / {

    # ...

    if ($http_cookie ~* "SPECIALID.*|$") {

        proxy_pass http://stage-cluster;

    }

    proxy_pass http://default-cluster;

}

灰度发布系统的架构设计考虑因素。

灰度发布,已经不是一个很新的概念了.一个产品,如果需要快速迭代开发上线,又要保证质量,保证刚上线的系统,一旦出现问题那么可以很快的控制影响面,就需要设计一套灰度发布系统.

灰度发布系统的作用在于,可以根据自己的配置,来将用户的流量导到新上线的系统上,来快速验证新的功能修改,而一旦出问题,也可以马上的恢复,简单的说,就是一套A/BTest系统.

它大抵的架构,应该是类似这样的:

其中分为几个部分:

1.    接入层,接入客户端请求,根据下发的配置将符合条件的请求转发到新旧系统上.

2.    配置管理后台,这个后台可以配置不同的转发策略给接入层.

3.    新旧两种处理客户端请求的业务服务器.

关于接入策略的设计上,从协议层来说,需要从一开始就设计是根据哪些参数来进行转发的,而且这些参数最好跟具体的协议体内容分开,这样减少接入层对协议的解析.举个例子,如果客户端的请求是走HTTP协议的,那么将这些参数放在HEADER部分就好了,接入层不需要去具体解析body部分的数据就拿到了转发策略需要的参数.当然,放在HEADER中的数据,因为没有了加密性,又是需要考虑的另一个问题.

当然,最简单粗暴的转发策略,可以根据客户端ip地址来做,这是比较粗略的一个划分策略.

同样的,新旧服务器要对新旧客户端的协议兼容,也是能做到灰度发布的根本,如何设计一个扩展性好的应用协议,这一点就不在这里考虑了.

接下来,还需要满足如果管理后台下发了新的转发策略,接入层应该是可以马上感知到然后切换到这个新的策略来的.有好些不同的做法.假如接入层是Nginx这样的服务器,使用者只是在上面写了自己的Nginx模块来实现策略的转发,那么可能还需要在每台接入服务器上部署一个Agent的服务,主要用于:

1.    接收管理后台下发的策略,更新Nginx配置,然后优雅重启Nginx服务.

2.    定时检查本台机器的Nginx服务的状态,进行上报.

如果接入层不是Nginx这样的服务,那么也可以做一个pub-sub模型的订阅者,用ZK或者Redis都可以,订阅管理后台下发的服务进行处理即可.

上周写完灰度发布系统相关的博文之后,有朋友表示灰度系统的实现太过简单了,因为我目前接触的系统确实比较简单,很多复杂的东西没有考虑周全,如果更大型的业务系统,涉及到的服务更多,还有如果掺杂着数据的迁移,就更复杂了.这里就把当时讨论的内容提取出来,主要的贡献者为滴滴的沈佳伟.

1.调用链上有多个业务服务的场景

考虑这样一个业务场景,假设对外提供了服务A给客户端访问,服务A后面会调用服务B,C,D,此时需要上线一个功能,这个功能涉及到了服务A,C的修改,但是服务B,D不需要变动,换言之,我们的意图是,如果一个客户端请求,走到了新的灰度服务A,那么最终这个请求也应该走到这次和A一起灰度的服务C上.

这里的处理策略,可以给客户端请求进行tag打标记的方式,比如经由新版本服务A处理的请求,全部打上tag A,而在服务C上,也有接入层进行转发,它转发的策略之一就是根据根据这个tag来进行转发,这个系统如下图所示:

上图中,请求首先走到了旧版本的服务A上,该服务没有对请求打上tag,所以后续访问的都是没有配套灰度的旧版本C服务.

上图中,请求首先走到了新版本需要灰度的服务A上,在经过该服务处理后,给请求打上了tag A,由于带上了tag,后续访问的都是配套灰度的C服务.

简单的总结下,涉及到一个调用链路上某几个服务需要灰度的情况,可以通过tag的方式,将走灰度服务的请求汇集到一起来,如果一个请求走到了一个灰度路径上,就打上一个tag,这样只有有这个tag的请求才能走到这条链路上后续也需要一起灰度的服务上.至于如何给请求打tag,如果是HTTP协议,那就很简单了,也是加Header的方式,否则需要在设计协议的时候就考虑协议的扩展性支持这个操作.

2. 涉及到数据的灰度服务

假设灰度的服务,需要使用到数据库,如果灰度前后数据库的字段保持不变,那么新旧两套系统使用同一套数据库就可以了.

如果前后数据不一致,需要处理的情况就比较复杂,分为以下几种情况.

·         部分灰度

在部分灰度的情况下,有部分请求到旧系统上,另一部分请求到了新的灰度系统上.走到旧系统的请求,还是照原样处理.但是走到了新版灰度系统的请求,需要同时将请求转发给旧系统上来对应的接口上修改旧系统的数据.如果走到新系统的请求查不到该用户的数据,还需要首先同步一份来新系统上.如果是事务性的请求,以写入老系统成功来做为操作成功的标准.

·         全部灰度

在灰度系统已经全部接管了线上流量之后,为了安全起见,仍然需要对新老系统进行双写,步骤和前面一样.

·         灰度完成

灰度完成与前面的全量灰度状态不太一样,区别在于前面的全量灰度状态下,仍然不能肯定系统一定是没有问题的,所以需要进行新旧系统的双写来保证数据可以在老系统上进行回滚.而在灰度完成状态,此时认为这个新版本已经完全通过了验证,无需再写入旧系统了.但是此时可能存在部分在灰度期间没有上线的用户,此时需要做一次同步,从旧系统上将这部分数据同步过来.

可以看到,这三个状态下,对新旧系统是否进行双写,做了严格的区分,目的只有一个:一旦新上线的系统出现问题,可以马上撤掉灰度系统,而这期间用户的任何修改在旧系统上都是可以找到的.

关于灰度发布和灰度配置的思考

最近团队在做一个集中化配置管理系统,根据运维团队的需求,要考虑应用灰度发布时配置部分变更的可能,需求是首先变更某个机房的某台服务器上的配置,进一步地,修改该机房所有服务器的配置,最后修改全局服务器的配置。这样的需求和通常理解的灰度发布有一定区别,暂且叫他灰度配置。本文主要理解下两种灰度的差异,并且简要说明两种灰度的实现方案。

集中管理和灰度概念

集中化配置管理系统:指的是指将原本散乱存放在各个服务器上的配置(通常的配置文件),集中在统一的平台进行管理,配置管理员可以在该平台上对配置进行增删改查,而每一个需要配置的节点在启动时主动向平台获取。进一步地,在配置发生变化时,主动通知到所有使用该配置的节点,以达到动态配置变更的目的。现在大的互联网公司都有自己的一套集中化配置管理系统,比如阿里巴巴的diamond系统,apache的zookeeper等。

灰度发布

应用的灰度发布指的是,新系统发布时不直接废止旧的系统,而是有一段新旧系统的共存时间。通过逐渐增加新系统承担的负载权重,直到完全替代旧的系统。这样的好处在于避免因为新系统存在功能异常或者设计上的不合理导致的服务完全中断,通过渐进式观测新系统替代旧系统的效果,达到平缓升级的目的。理解来说,就是在一段时间内,通过流量源头的开关控制,动态调整新旧系统承担的负载。

灰度配置

一个系统的服务器集群中,不同机器使用不同的配置,每一次,调整一批机器的配置,最终达到全系统配置统一。可以这么理解,相同系统的不同服务节点使用不同的配置,叫他灰度配置。

灰度发布和灰度配置的差异和实现

差异

灰度发布和灰度配置概念完全不同,灰度发布的过程像是现在社会的税收制度,每个人拿一点钱出来贡献党国,大家都是一样的标准,一视同仁。恢复配置更像是建国初期的打地主,圈出社会属性带有地主的一群人,把他们财产充公,特点是只是针对一部分人,但每一个被选中的人都要一分不剩。

灰度发布设计

关于灰度发布业界已经有比较成熟的实现,在需要灰度系统系统的前置流量入口系统上增加一个选择功能,先做一次发布。然后需要灰度发布的下游系统,将新系统部署上去,和老系统共存。灰度发布过程中,通过修改一个权重配置并推送到控制流量的前置入口系统上,将部分流量引向新的系统,并观察新系统的表现。逐渐地,继续修改权重配置,增加新系统承担的流程,直到新系统完全承担所有流量,下线老系统。

灰度配置设计

关于灰度配置,有一个种设计是,将配置做一个层级的划分。一共分为6层,包括:全局配置,全局灰度配置,机房配置,机房灰度配置,节点配置,节点灰度配置。优先级是,节点灰度配置>节点配置>机房灰度配置>机房配置>全局灰度配置>全局配置。也即是说对业务来说的一个配置,在底层存储实际上是6个配置。对于一个配置的需求者,每次启动获取6个配置的内容,然后根据优先级选择自己应该加载的配置。进一步地,他需要关注6个配置的变更情况,一旦当前配置被删除,需要重新根据优先级选择自己应该加载的配置内容。

灰度配置设计的思考

灰度配置方案存在的缺点

1.    配置的设计过于复杂,6个配置很可能让运维人员陷入混乱。

2.    配置级别不灵活,比如新增一个城市级别的配置就足够让所有应用跳脚;又在比如,因为服务器可能存在上线,下线或者迁移的情况,一次机房级别的配置变更,如何确认变更的服务器列表是否正确。

灰度配置方案缺陷分析

以上2个缺点,核心的问题在于一个配置管理系统做了一些可能不应该由他做的事情,比如负责节点的定义,机房的定义,灰度的定义等等,导致了设计上复杂和维护上的难度。当然,业务方有这样的需求,自然是要想方设法去做满足,以下提供一种新的设计方案,可以解决或者部分解决以上2个问题。

灰度配置新方案

新方案及运行时状态描述

1.    去掉6个级别的配置,改成2个级别,即全局配置和临时配置,优先级为临时配置>全局配置。

2.    增加机器分组的功能,该功能只在灰度发布时候临时使用。

·         正常运行时,一个配置需求者只需要关注全局配置以及自身的分组信息,灰度发布前,所有机器使用全局配置正常运行。

·         当灰度发布的时候,建立一个空的群组,为该群组设置临时配置信息,逐渐地,往该群组中添加机器信息,直到机房所有节点或者全局所有节点都放入。事情发生的时候,每个配置需求者发现自己的分组信息发生变化(即加入某个群组),就去获取该群组的临时配置信息,优先使用。

·         直到所有机器都归入该群组后,即表示灰度完成,所有节点配置一致。这时候,将全局配置更新为灰度配置,并取消组群关系。事情发生时,每个配置需求者发现自己的分组信息发生变化(即分组被删除),就去获取全局配置,正常地,因为全局配置的内容和灰度配置内容一致,配置需求者不产生任何变化(因为变化已经在灰度的过程中发生过了)。

新方案的优劣分析

1.    该方案将原来多级别的配置设计改成全局和临时2个级别,而且临时配置只在灰度发布时使用,设计上简单可控。

2.    群组功能足够灵活,将机器分组属性的判断抽象出来(重点),在满足业务灰度配置功能的前提下,保持自身的逻辑足够简单。

·         对于分组功能,刚开始可以由运维人员手动添加一些模板,每个模板组保存一个机房的服务器列表,然后在实际发布的过程中,可以直接copy模板组的内容,也可以根据实际需要构建一些临时的分组,以组为单位变更配置,这样就满足了运维人员分批推送配置的需求。

·         进一步地,可以构建一个运维管理系统,专门负责管理服务器的信息。将该系统和集中化配置管理系统进行对接,在每次发布时动态地获取分组信息,就能免去人工维护分组的麻烦。

·         当然,既然是分组,就会遇到一个问题,当遇到一台机器被归入多个临时分组的情况应该怎么办。有一种方法是对临时分组设置优先级,根据优先级决定读取哪个临时分组的配置信息,不过这种方法比较复杂,而且优先级很难定义且有存在重复的可能。另一种方法就是直接互斥,针对同一个配置,一台机器只能被放入一个临时分组中,这样逻辑会更简单。

9. 采用灰度发布的案例

9.1. 谷歌Gmail Labs

Gmail Labs是一个新特性橱窗,用户可以自己选择一些未正式发布的新特性进行体验,不喜欢可以关闭,在这个过程中,吃了螃蟹,也当了Google的小白鼠。

这个做法比传统的灰度要高明很多,更加尊重用户:

1、它没有强加用户,用户是否愿意当小白鼠完全自愿

2、新特性不是打包在一起的一个大版本,可以选择某几个喜欢的螃蟹尝尝

3、螃蟹不好吃可以扔掉,不用硬吃进肚子里引发肠胃炎

当然这些好处也是有代价的:

1、要开发一个labs平台实现新特性上架、独立尝试的功能,这可能要改动Gmail的前后台架构

2、新特性要按照一定规范来写,才能发布到这个平台上,可能会增加一些工作量

3、小白鼠用户增多之后,对系统的压力可能会有一定提升,因为每一位用户调用的界面都不一样了

既然Gmail Labs能够顺利发布,那么说明对Google来说,以上这些问题都不算问题。另外,现在展示的新特性,都注明了开发者的名字,那么,Gmail Labs可能会开放这个平台让外部开发者也能提交特性?这倒是很open的一种开发模式,非常适合Google的web app产品线。

9.2. 腾讯QZone

QZone是另外一个采用灰度发布的例子。大家都知道,QZone的改进是巨大的,从以前慢悠悠的老爷爷变成了一个充满青春活力的小伙子。其中经历了大小无数次的发布,他们的发布也都是采用了灰度发布的策略,用户数据的升级并不是大 面积的一次性升级,而是通过一个用户升级标志服务器,如果用户数据没有升级,后台会把此用户的数据逐步迁移到新版本上,然后将升级标志位置1,升级过程 中,用户仍然可以访问旧的数据,升级完成后的访问都将转发给新的版本。

QQ的很多产品发布都采用灰度发布,有些是抽取部分QQ号段升级成新系统,然后根据用户反馈再大范围升级。

9.3. 微信wechat

灰度、灰度、再灰度

    在变更后的部署方式上,微信在一些规则会限定不能一次把所有的逻辑变更上去,每一次变更一小点观察到每一个环节没有问题的时候,才能布局到全网上去。微信后台每一天可以支撑超过20个后台变更,在业界来说,通常做到5个已经是比较快了,但是微信可以做到快4倍。

腾讯内部的上线系统

而所谓灰度发布,是指在黑与白之间,能够平滑过渡的一种发布方式。AB test就是一种灰度发布方式,让一部用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面 来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。(在腾讯,灰度发布是最常采用的发布方式之一)

孙子兵法:古之所谓善战者,胜于易胜者也

常识上,解决一个复杂问题的时候,会用高明的技巧解决复杂的问题,这个不是微信团队的目标,他们追求的要做到让所有问题很自然和简单的方式解决掉。在周颢看来,微信架构的技术复杂点在四个要点:协议、容灾、轻重、监控。

微信架构

· 协议。手机终端跟后台服务器之间的交互协议,这个协议的设计是整个系统的骨架,在这一点做好设计可以使得系统的复杂度大大降低。

· 容灾。当系统出现了若干服务器或若干支架(宕机的时候),仍然需要让系统尽可能的提供正常的服务。

· 轻重。如何在系统架构中分布功能,在哪一个点实现哪一个功能,代表系统中间的功能配置。

· 监控。为系统提供一个智能仪表盘。

在协议设计上,移动互联网和常规互联网有很大的区别。首先有CMWAP和CMNET的不同,在中国现在有相当多的手机用户使用WMWAP连接,还有 就是在线和离线的概念,当QQ下线的时候叫离线,当你登录的时候叫在线。但是在移动互联网这两个概念比较模糊。从微信的设计中,不管在线还是离线系统表现 都应该是一致的。还有一个是连接不稳定的问题,由于手机信号强弱的变化,当时信号很好,5秒钟走到信号不好的地区,连接就必须断掉。这个中间带来不稳定的 因素为协议设计带来较大困难。此外就是资费敏感的问题,因为移动互联网是按照流量计费的,这个计费会使得在协议设计中如何最小化传输的问题。最后就是高延 迟的问题。

对此,业界标准的解决方案:Messaging And Presence Protocol:1)XMPP;2)SIP/SIMPLE。它的优点是简单,大量开源实现。而缺点同样明显:1)流量大:状态初始化;2)消息不可靠。

微信在系统中做了特殊设计,叫SYNC协议,是参考Activesyec来实现的。特点首先是基于状态同步的协 议,假定说收发消息本身是状态同步的过程,假定终端和服务器状态已经被迟了,在服务器端收到最新的消息,当客户端、终端向服务器对接的时候,收取消息的过 程实际上可以简单的归纳为状态同步的过程,收消息以及收取你好友状态更新都是相同的。在这样的模式之下,我们会也许会把交互的模式统一化,只需要推送一个 消息到达的通知就可以了,终端收到这个通知就来做消息的同步。在这样的简化模式之下,安卓和塞班都可以得到统一。这样的系统本身的实现是更为复杂的,但是 获得很多额外的好处。

让剩下系统实现的部分更加简单,简化了交互模式,状态同步可以通过状态同步的差值获得最小的数据变更,通过增量的传输得到最小的数据传输量。通过这 样的协议设计,微信可以确保消息是稳定到达的,而且是按序到达。引用一句俗话:比它炫的没它简单,比它简单的没它快,没谁比他更快,哪怕在GPRS下,微 信也能把进度条轻易推到底。

9.4. Ucloud高可用架构实践

DevOps成都站|架构与运维峰会活动总结地址:

http://mp.weixin.qq.com/s?__biz=MjM5NDE0MjI4MA==&mid=2656298704&idx=2&sn=68d5d42a9c26640a21eebd3253ca81c3&scene=1&srcid=0519IBq6Q2k77kYAQmXuofuV&from=groupmessage&isappinstalled=0#wechat_redirect

此处主要截取账户计费系统架构演进过程的六个阶段进行整理。

服务架构的演进过程

UCloud服务架构的演进主要经历了以下六个阶段:

a.单体模式;

b.具有灰度发布能力;

c.前后端分离;

d.服务化改造;

e.按SET部署;

f.分机房按SET部署,按SET进行跨机房热备容灾。

1. 单体模式架构上线业务系统

UCloud服务初期上线时的架构主要分三部分:

· 

PHP Web Conosle,负责所有前端展现交互、后台服务间逻辑组装;

· 

· 

平台类服务,账户、计费、监控、名字服务等公共服务;

· 

· 

各业务系统分数据中心后台服务的接入层。

· 

PHP Web Console、业务系统分数据中心的服务、平台类服务组合上线,Web Console 通过Protobuf与所有后端服务进行通信。

2. 具备灰度发布能力

要解决前面面临的问题,我们首先需要支持Web层灰度发布包含以下的灰度方式:

· 

无用户态特性按照 单IP -> IP段(地区) -> 到IP取模逐步灰度控制影响范围;

· 

· 

有用户态特性按照 单内部用户(开发账号) -> 内部测试账号 -> 用户分级逐步灰度发布控制影响范围。

· 

3. 前后端分离

· 

开发API Gateway 层用来管理后端 API 注册和管理、权限验证管理、流量控制;

· 

· 

开发API层,解决前台交互层,需要整合跨系统逻辑调用问题,前端只专注产品交互和用户体验;

· 

· 

开发统一的单点登陆Token,系统方便前端实现跨域API调用让前端代码可以完全静态化。

· 

在此阶段,完成前端展现可以独立控制发布,彻底实现了前后端解耦,API协议保证向前兼容,Web端可以随意重构交互优化前端架构,实现了跨域独立部署,独立的灰度策略互相之间不受影响,极大的提高了前端团队开发效率和稳定性。

4. 服务化改造

 对业务端API开发效率优化:

· 

按照业务模块化,所有业务API由后台产品研发部门独立部署发布上线;

· 

· 

抽象通用平台类特性例如:子账号特性,权限体系,计费等特性抽象公共能力让业务端在API中组装。

· 

总体目标:让业务API开发效率提升并单独部署维护,提高产品特性的研发迭代效率并提高稳定性。

5. 按SET部署

基础架构优化完毕,各个业务系统单独部署发布,开始对系统进行容量和容灾方面的考虑,从部分平台类系统开始考虑按SET部署架构测底解决容量和容灾问题,每个SET只服务一部分用户,保证遇到物理服务器宕机等故障情况下只影响部分用户或业务。

例如图上所示, SET 1 服务1 ~ 服务50000000 用户,SET 2 服务50000001 ~ 100000000 的用户,一个SET 出现问题只影响一个部分用户,不同的业务根据自身情况进行SET切分,规模大小也视情况而定,按SET部署后合理的划分方式下不同SET之间数据还可以互相迁移,来平衡搞负载或高容量的SET,极大的提高了可运维性。

6. 分机房部署SET

按SET部署架构改造完毕后还没有达到最理想的状态,如果所有服务部署在单机房还是可能会出现问题,机房整体出现断电、断网等故障还是会出现大面积影响。

· 

对SET架构进行分机房部署,让不同的用户运行在不同的机房中,这依赖一些基础设施比如跨机房光线专线。

· 

· 

跨地域SET在相邻节点部署热备,以便出现机房故障时能具备异地快速恢复服务的能力。

· 

总体介绍了UCloud在不同的阶段架构演进的一些过程和经验,架构没有最好的,只有最合适当前业务发展的架构。

9.5淘宝

9.6移动端APP的灰度发布

10. 参考资料

什么是灰度发布

从腾讯的“灰度机制”到产品的“灰度上线”,你了解多少?

“钱掌柜”分流发布模式

百度百科:灰度发布

A/B testing

A/B测试终极指南

互联网产品的灰度发布

聊聊灰度发布

一亿用户增长背后的架构秘密-腾讯微信技术总监周颢

马化腾谈互联网产品:灰度法则的七个维度

11.持续集成与灰度发布

一、持续集成

   

  持续集成(Continuous integration,简称CI)是一种软件开发实践,即团队开发成员经常集成它们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。

  持续集成的目的与价值:

    持续集成的目的不是减少build失败的次数,而是尽早发现问题,在最短的时间内解决问题,减少风险和浪费。从而让产品开发流程更加敏捷,缩短产品开发周期,在产品上线后,让用户用得更加顺畅。

    在没有应用持续集成之前,传统的开发模式是项目一开始就划分模块,每个开发人员分别负责一个模块,等所有的代码都开发完成之后再集成到一起提交给测试人员,随着软件技术队的发展,软件已经不能简单地通过划分模块的方式来开发,需要项目内部相互协作,划分模块这种传统的模式的弊端也越来越明显。由于很多bug在项目早期的设计、编码阶段就引入,到最后集成测试时才发现问题,开发人员需要花费大量的时间来定位bug,加上软件的复杂性,bug的定位就更难了,甚至出现不得不调整底层架构的情况。这种情况的发生不仅仅对测试进度造成影响,而且会拖长整个项目周期。

    而持续集成可以有效解决软件开发过程中的许多问题,在集成测试阶段之前就帮助开发人员发现问题,从而可以有效的确保软件质量,减小项目的风险,使软件开发团队从容的面对各种变化。持续集成报告中可以体现目前项目进度,哪部分需要已经实现,哪些代码已经通过自动化测试,代码质量如何,让开发团队和项目组了解项目的真实状况。

  持续集成的优点:

    1、快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。

    2、防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。

  持续集成的一些原则:

    1.所有的开发人员需要在本地机器上做本地构建,然后再提交的版本控制库中,从而确保他们的变更不会导致持续集成失败。

  2.开发人员每天至少向版本控制库中提交一次代码。

  3.开发人员每天至少需要从版本控制库中更新一次代码到本地机器。

  4.需要有专门的集成服务器来执行集成构建,每天要执行多次构建。

  5.每次构建都要100%通过。

  6.每次构建都可以生成可发布的产品。

  7.修复失败的构建是优先级最高的事情。

二、灰度发布

        

  互联网产品的发布大多都是做到这里就直接上线,替换了原有的版本,这种跳跃式的发布是非常危险的,如果产品影响面大,对项目成员的压力是非常大的。灰度发布是在发布新版本的时候,先切分部分流量给新版本,稳定了之后再切分所有流量到新版本。这样一旦有问题,马上修改切分的流量就可以,不需要重新发布,减少了发布风险。这种基于ABTest分流的灰度发布方式已经成为很多公司发布的一个必经流程。在灰度发布过程中,产品团队根据用户的反馈及时完善产品相关功能。目前业界一些著名的互联网公司(如google,百度)都是采用这种类似灰度发布的方式。AB Test系统就是可以实现灰度发布的系统。通过ABTest系统可以方便地以各种方式切换流量。

        

                     

  在敏捷开发领域,取消专职测试以后,灰度发布就更加重要。一旦新版本出现问题,能够通过我们的ABTest系统马上将所有流量切回稳定的旧版本。这样做的好处是:

  1、即时生效,无需发布,快速响应。

  2、可以渐进地调整比例。

  3、分流的维度丰富多样。

       

本文参考:

http://www.51testing.com/html/62/404362-822549.html

http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html

猜你喜欢

转载自blog.csdn.net/xl_lx/article/details/81130584