当前位置: 首页 > news >正文

基于 Nginx 实现一个灰度上线系统

灰度系统可以将流量分成多份,一部分走新版本代码,一部分走老版本代码,从而降低线上问题的风险。

正文从这开始~~

软件开发一般不会上来就是最终版本,而是会一个版本一个版本的迭代。

新版本上线前都会经过测试,但就算这样,也不能保证上线了不出问题。

所以,在公司里上线新版本代码一般都是通过灰度系统。

灰度系统可以把流量划分成多份,一份走新版本代码,一份走老版本代码。

而且灰度系统支持设置流量的比例,比如可以把走新版本代码的流量设置为 5%,没啥问题再放到 10%,50%,最后放到 100% 全量。

这样可以把出现问题的影响降到最低。

不然一上来就全量,万一出了线上问题,那就是大事故。

而且灰度系统不止这一个用途,比如产品不确定某些改动是不是有效的,就要做 AB 实验,也就是要把流量分成两份,一份走 A 版本代码,一份走 B 版本代码。

那这样的灰度系统是怎么实现的呢?

其实很多都是用 nginx 实现的。

nginx 是一个反向代理的服务,用户请求发给它,由它转发给具体的应用服务器。

这一层也叫做网关层。

由它负责转发请求给应用服务器,那自然就可以在这里控制流量的分配,哪些流量走版本 A,哪些流量走版本 B。

下面我们实现一下:

首先,我们准备两个版本的代码。

这里创建个 nest 项目:

# 全局安装 npm i -g @nestjs/cli # 安装成功后,直接使用 nest 命令创建项目 nest new gray_test -p npm

把 nest 服务跑起来:

npm run start

浏览器访问下:

看到 hello world 代表 nest 服务跑起来了。

然后改下 AppService:

修改下端口:

然后再npm run start

浏览器访问下:

现在我们就有了两个版本的 nest 代码。

接下来的问题是,如何用 nginx 实现灰度,让一部分请求走一个版本的代码,一部分请求走另一个版本呢?

我们先跑一个 nginx 服务。

docker desktop 搜索 nginx 镜像(这步需要科学上网),点击 run:

设置容器名为 gray1,端口映射宿主机的 82 到容器内的 80

现在访问 http://localhost:82 就可以看到 nginx 页面了:

我们要修改下配置文件,把它复制出来:

docker cp gray1:/etc/nginx/conf.d /Users/a0000/Desktop/learn

然后编辑下这个 default.conf

添加这么一行配置:

location ^~ /api { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://192.168.1.6:3001; }

这行就是加了一个路由,把/api/开头的请求转发给http://宿主机IP:3001这个服务。

用 rewrite 把 url 重写了,比如/api/xxx变成了/xxx

然后我们重新跑个 nginx 容器:

容器名为 gray2,端口映射 83 到容器内的 80。

指定数据卷,挂载本地的/Users/a0000/Desktop/learn/conf.d目录到容器内的/etc/nginx/conf.d目录。

点击 run。

然后看下 files 部分:

可以看到容器内的/etc/nginx/conf.d目录标识为了 mounted。

点开看看:

这就是本地的那个文件。

我们在本地改一下试试:

容器内也同样修改了。

在容器内修改这个文件,本地同样也会修改。

也就是说挂载数据卷之后,容器内的这个目录就是本地目录,是同一份。

然后我们访问下http://localhost:83/api/看看:

nest 服务访问成功了。

现在我们不是直接访问 nest 服务了,而是经历了一层 nginx 反向代理或者说网关层。

自然,我们可以在这一层实现流量控制的功能。

前面我们讲负载均衡的时候,是这么配的:

默认会轮询把请求发给 upstream 下的 server。

现在需要有多组 upstream:

upstream version1.0_server { server 192.168.1.6:3000; } upstream version2.0_server { server 192.168.1.6:3001; } upstream default { server 192.168.1.6:3000; }

有版本 1.0 的、版本 2.0 的,默认的 server 列表。

然后需要根据某个条件来区分转发给哪个服务。

我们这里根据 cookie 来区分:

set $group "default"; if ($http_cookie ~* "version=1.0"){ set $group version1.0_server; } if ($http_cookie ~* "version=2.0"){ set $group version2.0_server; } location ^~ /api { rewrite ^/api/(.*)$ /$1 break; proxy_pass http://$group; }

如果包含 version=1.0 的 cookie,那就走 version1.0_server 的服务,有 version=2.0 的 cookie 就走 version2.0_server 的服务,否则,走默认的。

这样就实现了流量的划分,也就是灰度的功能。

然后我们重新跑下容器:

这时候,你访问http://localhost:83/api/走到的就是默认的版本。

然后带上 version=2.0 的 cookie,走到的就是另一个版本的代码:

这样,我们就实现了灰度的功能。

但现在还有一个问题:

什么时候设置的这个 cookie 呢?

比如我想实现 80% 的流量走版本 1.0,20% 的流量走版本 2.0

其实公司内部一般都有灰度配置系统,可以配置不同的版本的比例,然后流量经过这个系统之后,就会返回 Set-Cookie 的 header,里面按照比例来分别设置不同的 cookie。

比如随机数载 0 到 0.2 之间,就设置 version=2.0 的 cookie,否则,设置 version=1.0 的 cookie。

这也叫做流量染色。

完整的灰度流程是这样的:

第一次请求的时候,会按照设定的比例随机对流量染色,也就是设置不同 cookie。

再次访问的时候会根据 cookie 来走到不同版本的代码。

这就实现了灰度功能,可以用来做 5% 10% 50% 100% 这样逐步上线的灰度上线机制。

也可以用来做产品的 AB 实验。

公司里都会用这样的灰度系统。

总结

新版本代码的上线基本都会用灰度系统,可以逐步放量的方式来保证上线过程不会出大问题,也可以用来做产品 AB 实验。

我们可以用 nginx 实现这样的功能。

nginx 有反向代理的功能,可以转发请求到应用服务器,也叫做网关层。

我们可以在这一层根据 cookie 里的 version 字段来决定转发请求到哪个服务。

在这之前,还需要按照比例来给流量染色,也就是返回不同的 cookie。

不管灰度系统做的有多复杂,底层也就是流量染色、根据标记转发流量这两部分,我们完全可以自己实现一个。

http://www.jsqmd.com/news/850248/

相关文章:

  • ComfyUI v0.21.1:最新版本发布,模型、节点、工作流与稳定性全面升级
  • BBDown:命令行驱动的B站视频下载完整方案
  • 政企级无人机管理系统,如何用一套方案搞定多行业巡检?
  • SaaS系统数据权限设计:基于RBAC与部门树的精细化控制方案
  • 一个简易的购物计算器
  • 5分钟终极兼容性修复:让魔兽争霸3在现代系统完美重生
  • 2026年AI写歌工具怎么选:4款工具使用场景和避坑记录
  • 从MATLAB到FPGA板卡:手把手教你用COE文件为Xilinx FIR IP核生成并加载低通滤波器系数
  • 放大电路性能
  • 数据库监控与性能调优
  • AI+Python构建数据分析智能体:小白也能学会,提升效率与可靠性,收藏必备!
  • 从Pandas到NumPy:用np.any()和np.all()优化你的DataFrame条件筛选,性能提升看得见
  • 新手也能看懂的逆向工程:用IDA Pro和C语言破解BUUCTF的XOR题
  • Win11系统下,手把手教你搞定Java 8环境配置(附JAVA_HOME、Path、CLASSPATH详细设置)
  • AI 智能体定制|企业专属数字员工解决方案
  • 车载倒车影像Linux驱动开发:从V4L2框架到MIPI CSI实战
  • 告别版本混乱!在Ubuntu 22.04上使用qtchooser轻松管理Qt 5.15和Qt 6.5的完整指南
  • 3分钟上手Hitboxer:免费解决游戏按键冲突的终极指南
  • 3步搭建Sunshine游戏串流服务器:免费开源的自托管云游戏解决方案
  • 数据库安全与权限管理
  • 《电流检测输出抖动的7个常见原因》 功率电子系统电流检测稳定性工程分析
  • Lenovo Legion Toolkit终极指南:拯救者笔记本性能优化完整方案
  • 魔兽争霸3终极兼容性修复:3步让经典游戏在现代电脑完美运行
  • SSH安全加固实战:从基础配置到公钥认证与Fail2Ban部署
  • iCloud 备份恢复聊天记录,这一步做错直接全白费
  • Lumerical案例 | 具有分布式电极的行波调制器
  • 在业务系统中强调结构最大化功能最小化
  • 卷积与ViT混合网络:设计原理、PyTorch实现与调优实战
  • 手把手教你给老旧咪咕盒子MG100/MG101刷机,瞬间变流畅(附固件下载与短接教程)
  • 电缆故障排查的高效保障:DLG-1 高压发生器技术与应用