当前位置: 首页 > 科技观察

前端灰度发布实施方案

时间:2023-03-15 20:43:54 科技观察

前言前段时间面试的时候遇到了前端灰度发布相关的问题。之前公司设计了一个前端灰度发布的方案,这个方案在多个系统上也是可用的,已经验证过了,最近有空整理一下,现在分享给大家,先走了最后为您提供一些代码实现。有兴趣的小伙伴可以查看关于灰度规则的一些重度算法的tips。它相对容易找到。本文的重点不在于算法,而在于贴合实际场景的灰度方案的实现。对大规模算法要求高的小伙伴可以自行搜索大规模算法,什么是bucketleak,token算法等灰度发布灰度发布一个函数(逐渐增加量)针对特定上网人群,规避新功能全面上线带来的风险。大白话,一个项目目前是1.0版本,但是想更新一个1.1版本,1.1版本内测没有问题,但是因为关键功能改了,所以想实现只针对部分在线用户的体验,并查看反馈。这时候部分用户需要继续使用1.0版本,部分用户需要使用1.1版本。如果1.1版本收到的问题严重到影响上线,那么1.0版本会回滚,受影响的用户范围比较小。如果1.1版本稳定的话,那么就直接过渡到1.1版本给所有用户。实现这个场景效果就是灰度释放。什么是灰度规则?灰度规则可以是业务信息,也可以是用户级别、性别、地区、客户端等设备信息。例如,设置灰度规则为广东地区用户发布1.1版本,则广东用户访问项目时会命中灰度规则,将他们转移到1.1版本,其他地区的用户继续使用1.0版本,这是一种常见的灰度发布方案。给大家介绍几个方案,大家可以对比一下,选择1.简单的ngxin卸载(推荐指数:??)只靠nginx做卸载的,算不上灰度发布,不过跟朋友聊过他们家小公司偶然show操作的实现,靠我写进去,说他们测试了两段代码,分别部署通过nginx加权轮询控制访问百分比(前提是客户端cookie没有alogo)前端引入了SDK(看了下源码,其实是在cookie中存储了一个随机不重复(但只是大概率不重复)的logo,第二次访问时,nginx通过cookie中的唯一标识返回对应的版本优点:简单,无后台操作相关缺点:仅依赖nginx加权轮询百分比控制流量,全部依赖前端,无法结合业务做流量分发可控性弱,当灰度版本出现问题时,只能通过修改nginx配置让收集用户回滚版本问题的能力差,只能等待用户反馈.清除客户端cookie后,用户需要通过nginx加权轮询重新进入,可能会分配到与之前分配不同的版本。2.nginx+lua+redis(推荐指数:????)tips:这个方案可能没找到好的资料或者对这个方案理解不深。我们感觉灵活性有些欠缺,结合复杂的业务很难做太多的灰色逻辑判断,如果有人用过这个方案,请告诉我。当用户请求到达前端代理服务nginx时,内嵌的lua模块解析nginx配置文件中的lua脚本代码lua变量,获取客户端的ip地址,并检查redis缓存中是否有内置值.如果有返回值,则执行灰度Version逻辑,否则,执行当前生产环境版本的nginx+lua+redis方案。网上资料比较多,大家可以自行了解。虽然我们对解决方案理解不透彻,但是从整个链接长度理论来看,这个解决方案的效率应该是比较高的,所以发了一些文章给大家。参考文章1[1]参考文章2[2]参考文章3[3]3。Server-siderenderingoffload(推荐指数:??????)serverrenderingoffload解决方案其实是我觉得比较好用的一个解决方案。这里我先简单介绍一下流程,后面会单独对其中的一块做一些介绍。比如你有多个页面,需要单独处理一些其他的细节)在后台管理中添加版本(实际上是让服务端去读取单个页面的index.html)当客户端访问服务端时,服务端sets-cookieandredis存储中,返回对应版本的index.html第二次访问经过服务器时,如果有cookie且redis已经有对应版本信息,则直接返回,否则会经过灰度过程。优点:灵活,可控性强,可以结合业务系统做灰度卷规则缺点:几乎是后台穿梭,对服务器有压力,需要更多相关优化,多页面应用使用起来比较麻烦4.客户端评论判断(难维护)(推荐指数:Tweety,不推荐)客户端通过评论条件编译做灰度。其实就是在代码层面根据灰度规则判断显示哪个版本的功能。该解决方案也被公司使用。灰度函数一旦太多,极难维护,不推荐,这里就不过多介绍了5.nginx+server+redis+【前端sdk】(推荐指数:??????)总体方案概览首先介绍一下上线的稳定版称为稳定版,而本次发布的新功能版称为测试版。通过请求灰度规则,命中灰度规则后,设置一个cookie作为客户端的标识,将用户ID存储在redis中,将用户重定向到指定版本的灰度规则接口请求,如果已经有cookie然后直接返回对应的版本,没有cookie然后再去redis,如果redis中有相应的信息就直接返回,如果不存在就走灰度规则识别过程。项目需要在特定时间触发灰度功能,点击某个按钮,或者进入某个页面,比如有些应用会弹出弹窗,告诉用户有内测版本,是否需要体验一下,点击同意后跳转到灰度版方案设计图标名词代号stable:正式生产环境(1.0版)beta:灰度版(1.1版)uuid:代码演示中,没有账号system并没有登录行为,所以在url上带上uuid作为用户ID走一遍具体实现过程(简单演示)分别创建两个html,假设两个项目,beta是新功能的灰度版本,和stable是当前的生产环境版本。前端引入sdk(前端sdk不是必须的,看业务场景使用)前端发起请求获取版本信息(如果引入了sdk,这一步可以通过配置完成)4.后端服务逻辑:后台实现代码//这里只是演示,直接通过链接获取用户id,实际场景应该是通过获取用户会话来识别用户相关信息constuuid=ctx.query.uuid;//可以输入灰度版的uuid,storeconstuuidsinthedatabase=['123','456','789']//redis中存储的用户id,如果redis被清理了,说明取消了用户的版本标识,这里只是简单的存储在一个数组中,实际应用场景考虑是否需要多个集合存储constredisUuids=[{id:'789',version:'beta'},{id:'333',版本:'稳定'}];上面代码的逻辑是,当uuid为123或456或789时,命中灰度规则,进入betauuid为789和333的用户已经存储在redis5版本中。效果:灰度问题处理操作Q:如果上线后灰度版本出现严重问题,需要紧急回滚操作答:直接在后台关闭灰度功能,清空redis,结束用户登录会话(实际上是清除客户端的cookie操作)问:需要指定某个用户进入某个版本A:在后台修改redis信息,结束用户的登录会话Q:只在项目中指定一个页面启用灰度答:可以在前端sdk中处理相关逻辑,并将相关页面路径作为列表,供前端识别不要(sdk最好动态引入,sdk放在cdn上)代码彩蛋代码公司后端是java实现的。感兴趣的朋友可以直接上代码github[4],总体设计思路是相同的注意点:为了方便运行和查看demo,我们通过dockercompose来运行,在docker和docker的前提下compose,可以直接通过命令运行示例docker-composebuilddocker-composeup-dlocalhost:8000项目的逻辑需要根据实际项目场景进行调整。前端sdk和java的代码没有发布,因为程序已经在公司实现了,不方便发布。大家可以按照大意来写。如果文章中有不对的地方或者有更好的解决方法,希望大家不吝赐教