您当前的位置:首页 > 电脑百科 > 程序开发 > 前端

分享一例有意思的灰度设计缺陷,浅谈灰度方案的设计

时间:2023-05-18 16:36:33  来源:微信公众号  作者: 阿里开发者

导读

灰度很重要,灰度的策略也需要结合实际情况进行灵活的调整,本文跟大家分享了一个前些时间发现的灰度设计bug。

一、案例分享

 

跟大家分享一个前些时间发现的灰度设计bug,这个bug蛮有意思,看似完美方案,但因为未考虑到一些技术特性,导致存在缺陷。为更通顺的说明,先进行一些名词介绍。

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

安全生产环境:(简称SPE)为保障线上稳定性提供灰度流量生产环境。发布从预发到生产环境前,需要经过SPE进行流量验证。

 

1.1 案例简述

 

同一个应用,需要消费同一个topic消息两次,因不同环境的配置不一致,导致消息存在消费遗漏。

 

1.2 案例背景

 

需求的主要修改的点是将历史各异的结算模型改成统一结算模型,新老模型相差较大。在notify消息的处理上,原本是想在同一个consumer处理类中改写,但成本较大,且考虑到老模型后续是需要下线的,从代码整洁的角度出现,新写了一个消息处理类,使用另一个group组订阅,最终的结果就是同一个topic消息会被两个group组订阅,并由两个consumer类去消费。

 

1.3 方案描述

 

原灰度方案如下:设定一个时间作为灰度生效时间,再通过消息中买家的尾号作为切流条件。当一个消息被接收时,会先判断当前时间是否大于灰度时间,若满足大于灰度时间的条件,则判断买家尾号是否在灰度切流范围中,均满足时,走新的结算流程。若两个条件有一个条件不满足,则走老结算流程。

 

1.4 方案缺陷分析

 

上述方案,一般而言,是一个很不错也很完备的方案,但结合本次结算模型迁移的背景,则存在一个缺陷。缺陷的由来即是“双消息”。那么双消息处理是怎么引发问题的呢?原因在于灰度配置文件在安全生产和线上生产间阶梯推进时,需要等待1小时,这一小时会导致部分消息被遗漏。假设当前SPE和线上生产已同步推进至10%,此时SPE的配置推进至20%,线上生产依旧保留10%,那么双消息一条走到SPE,另一条走到安全生产时,即会出现问题,因为SPE的老group实现类只关心80%-100%的流量,而线上生产环境只关心0-10%的流量,中间存在消息遗漏。逻辑如下图:

 

1.5 案例的特殊之处

 

1.结算模型的升级,结合业务考虑,引入了双消息消费的方式。

2.新老consumer无差别监听消息进行消费,造成消费遗漏。

3.SPE安全生产停留1小时的机制。

 

1.6 改进策略

 

1.灰度时间总开关不变

2.买家尾号的灰度策略改为“尾号为K,区间生产时间为V”的KV对,其中V是一个未来时间,且“V值>系统时间+安全生产停留时间”。如下,从50%流量推至100%,100%的流量配置生效时间是一个未来时间。


 
[
    {
        "rate":5000,
        "whiteList":[
        ],
        "activeTime":1682928000000
    },
    {
        "rate":10000,
        "whiteList":[




        ],
        "activeTime":1683795376000  //未来时间
    }
]

 

在跟进完上述问题后,我查阅了过去一年部门故障复盘文档,基本所有的故障和资金事件复盘,均有提及灰度手段。而像本案例中,于“不确定行为”进行灰度的控制,是新人们常见的误区。因此,结合自己在交易线的一些经验,谈下我认知中的灰度,并将阐述我理解的MVP版灰度方案,至少需要些什么,灰度设计中需要注意什么。

二、设计一个MVP版的灰度方案

 

2.1灰度方案是什么?

 

在聊how的问题前,有必要先讲一下WHAT和WHY。先聊一下WHY,假设没有任何管控流程,代码发布后立即全量上线,又恰巧不幸地出现系统、数据或逻辑等方面的问题,那一场灾难也就随之而来,而且业务体量越大,风险&舆情&资损的敞口也就越大,损失越不可挽回。因此,发布流程需要必要的管控和监督,将风险控制在有限范围内,这样的发布流程即是灰度。平滑过渡是灰度重要特征,这个特征也决定了灰度发布的作用至少有两点:

1.降低发布带来的风险,让少部分用户先使用新功能新版本,提前小范围内发现bug或性能问题,及时做好修复,降低新功能新版本的影响。

2.通过新老版本对比,观察新功能带来的效果,更好起过渡效果。

 

2.2 MVP版的灰度方案( Minimum Viable Product最小可执行版本)

 

2.2.1 明确灰度维度

常见的灰度规则有用户尾号(买家或卖家),业务单据id(如商品、订单、结算单、运单)、黑白名单、人群圈选(如定向投放)。黑白名单和人群圈选有点类似A/B-test,能比较精准的用于线上功能测试。一般用于两种场景:

1.风险极大,而功能测试又无法完全覆盖的场景,可以使用白名单和人群圈选做第一步的灰度策略。

2.功能存在争议,beta版功能测试,可以使用此法去收集反馈。

而采用用户id或业务id作为灰度条件,是更为通用的方式,这两种方案的流转模式如下:

 

尾号id灰度策略一般会与白名单策略组合使用,更稳妥的达到管控效果,结合我目前的项目实践,有一种较为万能的灰度公式分享给大家。

“1.白名单(个别用户)--> 2.买家尾号灰度1% -->3. 尾号3% -->4. 尾号10% -->5. 尾号30% --> 6. 尾号灰度50%-->7. 尾号灰度70%-->8. 尾号灰度100%”。

多数场景下,这一套公式流程是比较适用的。也许有同学会有疑问,是否可以采用“卖家id”灰度维度,多数情况下是可以的,但以卖家id为灰度规则,更容易命中到超大商家,可能带来的影响有两个,1.集中的单据被影响,2.相较买家购买,卖家维度更容易命中爆品热度的商品,引发数据库热点。因此,灰度维度的选择,是一件需要深思的事,我认为有几个原则需要遵守。

1.样本避免以偏概全,尽量保证样本的随机性,近似均匀分布。

这一点很好理解,比如你想统计有多少人坐过杭州地铁,然后你跑到杭州地铁站去做问卷调查,除了得到100%的结果,你一定会得到更多的白眼。同样,在灰度维度选择上,也需要保持样本的随机性。如用户id、商品id,一般就可以较好的满足日常灰度的需要。而像业务的人群id,在筛选时就得严格关注一下样本的随机性。

2.筛选条件需要由严至宽,逐步放开。

举一个例子,是去年进行某支付退款业务的中台升级时,在完成所有验证后,灰度策略里包含了一条,即逐步放开退款单的金额 ,从“控制退款单1元-->退款单10元-->30元-->100元-->300元-->全量放开”。这就是一种典型的风控层面的灰度策略,由严至宽。

2.2.2 做好过程观察和推进

灰度是一个逐渐由白至黑的过程,在这个过程中,“灰度可观察”和“灰度流程管理”,都需要做好。

灰度可观察

灰度过程必须可观察,这样才能及时发现问题,真正发挥灰度的价值。我总结了四个点,是灰度可观察的最小条件集,包括完备的流量日志、核对告警、反馈渠道及时触达和性能关注。以下逐一阐述。

策略一:完备的流量日志

完备的日志对于灰度过程中的问题发现是非常有必要的,将详细的处理逻辑,尤其是报错和异常的日志,是灰度可监控的必要条件。一方面,技术同学可以通过观察日志的错误日志,进行流量健康度的观察,另一方面,也可以结合 sunfire的统计监控能力,对灰度过程的报错做阈值告警。

策略二:核对告警

灰度项目中,核对也是常用的观测策略,无论是新业务的逐步上新或是新老业务的逐渐切换。如一个重资金相关的新业务上线,在逐步的灰度过程中,使用核对是验证非法单据的出现。这也是我日常业务跟进中经常使用的策略,比如RP3迁移灰度时,对打上新逻辑标的订单做校验。完备的日志是从系统处理的角度进行观察,而监控核对是从数据的角度进行另一个维度的观察,相辅相成不可缺少。

策略三:内部反馈渠道&舆情关注

这种策略一般用于白名单灰度的情况,且选中的白名单是与集团服务同学平时沟通较多且友好的商家,在百分比切流前,进行白名单个别商家的试点,关注异常情况。白名单内测后,切流阶段,如果有不可规避的风险,需要技术同学时刻关注客服反馈,必要时需要给客服统一的话术。

策略四:关注灰度过程中的性能问题

灰度不仅应用于功能,也可用于性能观察。灰度过程的流量是逐步增大的,新老功能的差异带来的性能影响,也是逐步放大的。比如一次改动中,新老流量模型中,对于某个信息字段的获取走的不同信息渠道,那么新老模型的性能差异就需要关注。此时不仅是业务的日志监控,应用系统的监控也需要安排上,尤其是灰度范围扩大的一段时间里,尤其需要关注接口性能,包括依赖rt变高,自身rt变高,数据库热点等问题。

灰度流程管理

好的灰度流程,需要具备优雅、可靠的特征。我认为“有序的推进”和“可及时回退”是灰度流程中必要的考虑。

有序的推进

从0到1的灰度过程,是一个边观察边推进的过程,通过日志、核对、自动化等手段做到有效观察后,在积累一定量级的单据后,再进行逐步的放开。需要关注的是如果配置非法状态下,是否保证老逻辑是否仍能正常消费。举例说明,下方伪代码是根据用户的尾号进行判断,在灰度配置平台里进行尾号的数字配置,那么,这一段代码看似正常,但实际隐藏着较大的风险:


 
//预期从灰度配置文件中读取一个int型的值,但配置中grayRange设置了一个字符串型“50%”,
int grayRange = GrayHanlder.getConfig("灰度配置id").getInteger("grayRange");3
if(userId mod 100 < grayRange){
    //走新逻辑
}else{
    //走老逻辑
}

 

上述代码在执行时,会报错,导致新老逻辑都不会走到。当然,在实际业务需求中,很少发生这么低级的错误,但我的意思是,依赖于配置的灰度推进,需要确保灰度逻辑进行必要的验证,灰度的推进也需要极其的谨慎。一般而言灰度代码只是一个if+else,但其背后影响却极大。

 

灰度流程推进的前提,一定有效的流量观察之后,而不是形而上的依据灰度时长,请确保这一点。分享一个真实的故障案例:

案例名:某B系业务的会员子账号id写入错误导致无法处理退款。

故障原因:因修复一个会员登录bug,更新了一个冷门字段的获取逻辑,某B系业务使用此字段做权限控制,导致业务受到影响。

灰度过程:此案例中的发布应用,在发布过程中进行了灰度停留,但灰度时间是晚上,而被影响的B系业务特性决定了晚间时分是流量低谷期,导致灰度过程中的问题未被及时关注,灰度流程未发挥应有的效用。

灰度改进:涉及会员和商家操作的系统,灰度发布时间包含商家操作高峰期(上午8点--10点)。

灰度回退

当上线功能的表现不符合预期时,需要考虑控制灰度回退。一般在灰度的配置文件中,需要引入逻辑开关,值为true或false,命中true后,才会进入更细粒度的灰度命中。所以当结果观察不符合预期后,可以快速推进配置为false,必要时,走紧急审批。确保没有新流量走到灰度流程中。

灰度回退仅能阻止问题的扩大,但已出现问题的单据需要做好妥善处理,一般而言,有两种方案。

1.修订数据:新写修正接口或批量更改Db数据,但需要注意合规问题。

2.快速修复并发布新版本,利用升级来“回退”,覆盖上次灰度发布的修改。

 

2.3 灰度工具

 

这里仅讲一下服务端常用的灰度工具,一般都是轻量配置的平台,将配置内容脱离于代码之外,可以清晰快捷的推进,在灰度推进时,仅需做配置更新即可,不用发布代码。配置可以简单成一个String,也可以是一个json,举例如下。

      {
        "flag": true,           //总开关,true为开启,false为关闭恢复
        "buyerAccessFlow": 10,  //用户尾号控制,当前为尾号 0-9用户进入恢复
        "amountLimit": 30000    //控制金额,金额小于300元,才进入恢复
      }

 

三、关于灰度其它常见的问题

 

3.1 机器分批发布不是严格意义上的灰度策略

 

许多同学对于灰度的认知还不多,认为分批发布也是一种灰度策略。其实严格意义上讲,应用的分批发布更多的是出于对系统稳定性的考虑,而不是灰度验证的考虑。从“可回退”的角度看,分批发布过程中,即使发现了问题,发现了脏数据,那数据也都是随机的,数据无法通过特征来找出数据,也就无法对脏数据进行订正或回滚,所以不是严格意义上的灰度策略。

 

3.2 灰度设计的一致性原则

 

灰度意味着线上存在两套处理规则或流程,一条业务单据在两套流程中处理的结果一般也是不一样的,因此确保单据在灰度过程中的一致性非常有必要,否则很可能引发线上问题,这里先举一个真实发生的例子

案例名:电商业务增加一种退款打款渠道,灰度策略不合理导致双渠道出账的情况。

案例描述:RPC调用退款同意时,第一次命中尾号灰度,走进组合渠道中,但组合渠道里出现调用异常,但此时渠道会进行自身的重试。在重试期间,用户二次点击,此时灰度策略有变化,导致走到了另一个组合渠道,进行了打款并成功。

 

案例分析:发生的原因在于打款事项的幂等被破坏。两个渠道无法感知对方的打款行为。

案例解决:在申请退款时,即打上标,将灰度行为完全依赖于标识,后续所有的处理依标进行,避免不同调用引起的灰度不一致的行为。后续退款相关的灰度行为,都前移至了申请退款阶段,此时命中灰度规则后,即会给它打上一个灰度标,后续的行为完全按标行走。

上述案例,是一个非常经典的问题,即灰度过程中数据一致性未能做好保证,导致出现两种打款策略组,破坏了幂等。那么怎么样保证灰度一致性原则呢?我认为有以下三个原则需要遵循:

原则一:灰度命中处理只能被一次消费

如上述案例,如果将灰度的判定放在“同意退款”,那就非常容易出现前后两次调用时,走到不同处理流程的尴尬情况,反之,我们可以巧妙的将灰度判定前移至“申请退款”,并打上相应的标,后续“同意退款”则按标进行即可,保证灰度命中处理只被一次消息。“同意退款”是想灰度的功能,但“申请退款”才是真正的灰度对象。所以想灰度的功能跟实现灰度的对象,并不一定要一致。

原则二:确保不同环境的灰度一致性

许多带安全生产环境的应用,从预发到线上前,需要在安全生产环境观察1小时以上,包括应用代码发布或配置发布。这中间的时差,极其容易引发灰度的混乱,比如开头说的那一个case,由于notify无差别的往安全生产和线上生产环境发消息,应用在两个环境中的配置不一致,导致消息被过滤的问题。

这种问题,就像使用原则一的方法进行预先打标处理,也是无法规避的,比较好的处理方法是,制造一个时延周期,确保线上生产和安全生产的一致性。比如推送一个未来的生效时间,且确保生效时间晚于全量发布完成后的时间,这样即可确保两个环境的一致性。

原则三:确保不同应用的灰度一致性

如果灰度流程涉及多个应用,那么灰度逻辑需要确保一致。简而言之,一个形如“A-->B-->C”的链路中,要么保证B系统无视A系统的灰度条件,要么确保灰度逻辑仅在A系统中进行判断。

 

3.4 前端灰度策略

 

前文提到的灰度策略,我均是从一个服务端的视角考虑,其实在前端或web端也有一些常用的灰度技巧,这里简单聊一下。

1.CDN资源分流

前端资源放在CDN上,每次发布新版本,资源即增量的传到CDN并指定唯一版本号。在处理请求时,依据前端策略来分流不同用户使用不同版本的CDN,展示不同的样式。此时,相应的后端接口,需要依据参数来控制灰度策略,区分前端不同的请求。一般在类似于账单业务升级时,会用到这种策略。因为前后端都需要灰度,所以需要由前端控制灰度策略,后端进行参数兼容,保证账单的多样性。

2.客户端分流

客户端分流的策略与CDN资源一样,由客户端来控制灰度分流,根据客户端传来的参数和版本号,结合当前的放量策略来决定服务情况。客户端分流的策略也会更多,如用户设备系统、App版本号、app安装渠道、用户ID、设备ID。

四、写在最后

 

灰度很重要,灰度的策略也需要结合实际情况进行灵活的调整。本文中提到的策略、观点均是本人一得之见。引玉之砖,欢迎大家讨论。

作者:崔剑飞(木祎)

来源:微信公众号:阿里开发者

出处
:https://mp.weixin.qq.com/s/QPYprfHeHBnh38HQBh_K-w



Tags:灰度设计   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
分享一例有意思的灰度设计缺陷,浅谈灰度方案的设计
导读灰度很重要,灰度的策略也需要结合实际情况进行灵活的调整,本文跟大家分享了一个前些时间发现的灰度设计bug。一、案例分享 跟大家分享一个前些时间发现的灰度设计bug,这个b...【详细内容】
2023-05-18  Search: 灰度设计  点击:(403)  评论:(0)  加入收藏
▌简易百科推荐
20k级别前端是怎么使用LocalStorage的,想知道吗?
当咱们把咱们想缓存的东西,存在localStorage、sessionStorage中,在开发过程中,确实有利于咱们的开发,咱们想看的时候也是一目了然,点击Application就可以看到。前言大家好,我是林...【详细内容】
2024-03-26  前端之神  微信公众号  Tags:前端   点击:(12)  评论:(0)  加入收藏
前端不存在了?盲测64%的人更喜欢GPT-4V的设计,杨笛一等团队新作
3 月 9 日央视的一档节目上,百度创始人、董事长兼 CEO 李彦宏指出,以后不会存在「程序员」这种职业了,因为只要会说话,人人都会具备程序员的能力。「未来的编程语言只会剩下两种...【详细内容】
2024-03-11  机器之心Pro    Tags:前端   点击:(9)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown &mdash;&mdash; 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  OSC开源社区    Tags:Vue   点击:(11)  评论:(0)  加入收藏
两年前端经验还不会手写Promise?
什么是promise?当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码...【详细内容】
2024-03-07  海燕技术栈  微信公众号  Tags:Promise   点击:(23)  评论:(0)  加入收藏
网站开发中的前端和后端开发有什么区别
前端开发和后端开发都是干什么的?有哪些区别?通俗地讲,前端干的工作是用户可以直接看得见的,而后端开发的工作主要在服务端,用户不太能直接看到。虽然前端开发和后端开发的工作有...【详细内容】
2024-02-21  CarryData    Tags:前端   点击:(32)  评论:(0)  加入收藏
网站程序开发中的前后端分离技术
随着互联网的快速发展和技术的不断创新,传统的网站开发模式已经难以满足日益增长的业务需求。为了提高开发效率、增强系统的可维护性和可扩展性,前后端分离技术逐渐成为了网站...【详细内容】
2024-01-31  网站建设派迪星航    Tags:前后端分离   点击:(23)  评论:(0)  加入收藏
如何优雅的实现前端国际化?
JavaScript 中每个常见问题都有许多成熟的解决方案。当然,国际化 (i18n) 也不例外,有很多成熟的 JavaScript i18n 库可供选择,下面就来分享一些热门的前端国际化库!i18nexti18ne...【详细内容】
2024-01-17  前端充电宝  微信公众号  Tags:前端   点击:(69)  评论:(0)  加入收藏
Vue中Scope是怎么做样式隔离的?
scope样式隔离在 Vue 中,样式隔离是通过 scoped 特性实现的。当在一个组件的 <style> 标签上添加 scoped 特性时,Vue 会自动为这个样式块中的所有选择器添加一个唯一的属性,以...【详细内容】
2024-01-04  海燕技术栈  微信公众号  Tags:Vue   点击:(80)  评论:(0)  加入收藏
vue3中 ref和 reactive的区别 ?
最近有朋友在面试过程中经常被问到这么一个问题,vue3 中的ref 和 reactive的区别在哪里,为什么 要定义两个API 一个 api不能实现 响应式更新吗??带着这个疑问 ,我们 接下来进行逐...【详细内容】
2024-01-03  互联网高级架构师  今日头条  Tags:vue3   点击:(38)  评论:(0)  加入收藏
React18 与 Vue3 全方面对比
1. 编程风格 & 视图风格1.1 编程风格 React 语法少、难度大;Vue 语法多,难度小例如指令:Vue<input v-model="username"/><ul> <li v-for="(item,index) in list" :key="inde...【详细内容】
2024-01-03  爱做梦的程序员  今日头条  Tags:Vue3   点击:(72)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条