概述

灰度发布是最近一年在国内互联网讨论较多的一个话题。灰度发布在国外并没有明确的定义,在国内的百科上如此定义

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

由此也可见灰度发布很多时候都和AB测试混在一起,但实际上灰度发布还包含了多级发布的概念。

11年,Facebook的David Wei写了一篇文章《代码和产品发布的几种方式》明确分析了下几个概念:

1、多级发布:也可以称为分步代码发布,是一种代码发布的方式。基本操作是整个团队共用一个代码库,一定频率(比如每天一次,或者每周一次)把整个代码的最新版本做一个新的发布分支(release branch),把发布分支逐步发布到产品线。

2、AB测试:这是一种很成熟的概念,是产品发布的常用手段。比起分步代码发布,AB测试往往有更长的周期(比如几个星期甚至几个月)。基本操作是产品的开发者加一个或者多个配置控制(一般每个产品配置应该带有配置的ID),允许通过调节相应的配置来让一个产品发布到“逐步选择”的用户群。

从概念中可以看出多级发布和AB测试中最重要的区别:面向对象不一样。多级发布针对的是代码发布,AB测试针对的产品发布。本文主要讨论代码多级发布相关的需求和实现方案。

需求场景

在具体的互联网应用中(主要针对如下架构)

多级发布的需求场景如下:

第一种:单个业务模块上线,属于具体一个业务中的一个模块,非基础模块。有如下的特点:

  • 50%的上线需求是这种场景。
  • 上线流程:单机器-》多机器-》全部机器 的过程。
  • 上线时间间隔非常短,一般在半个小时内完成全部上线。
  • 会对用户带来影响,比如说用户不停刷新有可能看到不同的版本。

第二种:基础库模块上线。大部分的基础库上线会和第一种业务模块上线类似,但部分上线(尤其是哪些影响业务模块较多,修改较大,有高性能要求)也会有如下特点:

  • 整体预估20%的上线需求,其中5%有如下特殊需求。
  • 可能的特殊需求:分业务系统逐步上线到所有机器。
  • 上线时间间隔有可能持续较长时间,比如说几周以上。
  • 基础库上线一般不会对用户带来影响。

第三种:多业务多模块上线。一般这种上线的项目都是非常重要或者有重大功能修改的项目,重要性非常高。特点如下:

  • 30%的比例。
  • 一般上线流程是分业务上线。并且大体原则是从后(端)到前(端)。跨系统依赖的会梳理出顺序,按照次序先后上线。
  • 原则上各个模块之间上线间隔都在小时或者分钟级别。
  • 对于具体用户可见的部分会采用,有可能会用到长时间间隔的上线方式。

难点&解决方案

多级发布的主要难题有以下几个:

  1. 监控完善到位。在每一级别的发布中,如何能够快速的通过监控系统发现问题,包含功能异常、性能异常。
  2. 策略灵活可控。比如说能够支持指定用户查看某一级别的发布版本、能够灵活的支持动态调度和动态扩容的需求。
  3. 用户体验无损伤。在发布的过程中,最好能够保证用户不会出现刷新版本频繁切换的问题。PS:该问题在facebook也存在,但据说目前不care。
  4. 发布过程可测试。在发布的过程中,每一个阶段都是可以方便确认功能正确性的。

同时多级发布也有一些限制,比如说同一个模块的最多只能有一个上线流程在进行,也就是不支持同一个模块多个版本并行上线

其中监控需求,本身是一个相对独立的需求,不在多级发布中考虑,那么多级发布只需要解决2、3、4三个难题。

多级发布解决方案按照不同的实现层度如下:

第一、实现多级发布基本功能:按照比例实现多级发布

假设总共有16台机器,分成8级发布,则可以按照1/8的分级方式进行上线发布。比如发布了第一级别后如下图:

为什么要按照比例,而不是直接给机器划分级别呢?主要是处于几个考虑:

  1. 给机器不同的标签定义会导致机器的异构化带来维护的难度。
  2. 无法支持机器动态调度的需求。
  3. 无法支持机器数目扩容的需求。

第二、保证用户体验:采用一致性哈希负载均衡

如何保证用户体验不受到影响的关键是:在多级发布的时候保证一个用户的请求固定的落在一个发布级别中。那么对应的方法就是:前端接入层和运行层之间采用一致性哈希负载均衡算法。

这种算法有几个依赖:

  • 接入层和运行层的各个节点是无状态对等的。原则上都会满足。
  • 在代码发布阶段,最好不能有机器的变更。如果有机器变更则会导致部分用户在某一时刻出现业务版本的切换(原则上影响也不大)

对于一些默认不是一致性hash算法的,也可以在代码发布的时候,把前端接入层和运行层之间的负载均衡方法切换到一致性哈希。

第三、可测性和灵活性:接入层引入规则通用库。(如果接入层采用Nginx做反向代理,那么就是一个nginx扩展)

可测性是指:业务模块的阶段性发布能够理解可测。这种需要只需要接入层规则通用库能够支持通过Http请求某一个参数来进行强制的请求分流即可。比如说通过参与version来指定对应请求分流的版本,具体比如说URL中有参数version=1,则分流到多级发布中的第一级。

灵活性:主要是指其他一些测试性的需求,比如说强制某些用户分流在多级发布的某一级,这些同样可以可以在接入层中实现。

本文首发xlq的博客(转载请保留)http://blog.xiuwz.com/2012/03/05/%e6%b5%85%e8%b0%88%e7%81%b0%e5%ba%a6%e5%8f%91%e5%b8%83%e4%b9%8b%e5%a4%9a%e7%ba%a7%e5%8f%91%e5%b8%83/