你想知道的前端灰度方案都在这了

10,744 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

背景:

用户打开页面的时候,需要根据页面的活动 id,渲染不同的迭代版本,例如活动 A 使用的代码是 v0.0.1(featureA),活动 B 使用的版本是 v0.0.2(featureB)

image.png 当然灰度策略不单单是活动 id,可能包括如下情况

  1. 按流量百分比
  2. 按地区
  3. 用户id
  4. 活动id
  5. 按ip
  6. 等等

目的

让产品应用逐步投放到市场,逐步发现问题,修改问题,适应市场

办法:

1. nginx + lua + apollo

推荐指数:⭐️⭐️⭐️⭐️

修改成本:⭐️⭐️⭐️

具体做法:用户请求 nginx,nginx 根据灰度策略判断当前用户需要渲染的版本后返回对应版本的 html, 判断版本的逻辑由 nginx 处理,灰度策略存放在某个数据库或者 apollo(比如白名单 ip,白名单 id,百分比值)

优势:

  • 不改动前端业务代码,维护简单

劣势:

  • 改造成本稍大,需要后端或者运维支援、需要使用 lua 语言,可能需要修改构建流程。

2. bff + apollo

推荐指数:⭐️⭐️⭐️

修改成本:⭐️⭐️⭐️⭐️

具体做法:类似第一种,只是把 nginx 换成了 node.js,适合有 bff 层,且 bff 承担渲染前端页面功能的项目

优势:

  • 不改动前端业务代码,维护简单

劣势:

  • 对于没有 bff 的项目或者有 bff 但不承担渲染任务的项目,改造成本大,需要引入 bff 层

3. 前端 ajax 请求后端接口。

推荐指数:⭐️

修改成本:⭐️⭐️⭐️⭐️⭐️

具体做法:用户请求 nginx,nginx 返回 html ,前端渲染 html, 执行 script 写好的 ajax 脚本,请求后端接口,拿到灰度的版本号,最后前端动态加载不同版本的入口 main.js。在这里灰度策略、灰度版本判断逻辑都放到了后端

优势:无

劣势:

  • 改造成本比 2 还大,前端和后端都要改动

  • 前端同步 ajax 会延迟页面加载,导致白屏,用户有感知,可能会有重定向。

4.前端业务代码逻辑判断

推荐指数:⭐️

修改成本:⭐️⭐️⭐️⭐️

具体做法:前端在代码里面 if else 判断,例如 A用户使用 A 组件,B 用户使用 B 组件

优势:

  • 纯前端

劣势:

  • 不适合项目级别控制的 A/B test,只适用于组件级别
  • 代码冗余,可能有多版本,多个 if 判断 ,维护麻烦

5. 前端自己做资源的入口判断

推荐指数:⭐️⭐️⭐️⭐️

修改成本:⭐️

具体做法:用户请求 nginx,nginx 返回 html ,前端渲染 html, 执行 script 脚本,前端判断灰度的版本号,最后动态加载不同版本的入口 main.js。在这里灰度策略、灰度版本判断逻辑都放在前端 html 内的 script 脚本处理。

优势:

  • 无需后端运维参与改造。
  • 项目级别的灰度,不修改具体的业务代码

劣势:

需要灰度的时候,需要前端修改,增加前端工作量

看了上面几种情况,再总结一下,灰度发布的本质问题其实就 3 个

1. 打包的资源怎么处理,即怎么区分 featureA 的资源还是 featureB 的资源

通常我们打包的时候,只会放到这3个地方,怎么记录版本号呢?

  1. 上传到 cdn

可以通过资源地址的 hash 值判断

  1. 放到云服务器

需要每次打包出来的目录名不一致,然后根据资源目录名称,本质也是地址 hash 不同

  1. docker 镜像

通过镜像的版本号来判断

2. 灰度策略放在哪里

  1. 放到后端业务的数据库
  2. apollo
  3. 前端

3. 灰度版本的判断逻辑放在哪

  1. 可以放到 nginx
  2. 可以放到BFF(Node.js)
  3. 可以放到前端

但是这三个问题一结合,就会出现很多的灰度方案,结合自身项目选型的难度就会增大,可能还会涉及到 Docker ,多套服务器环境的情况,例如,使用灰度的时候,是灰度到另一套环境呢,还是只是前端资源的灰度。希望这篇文章能给大家带来一点启发。