导图社区 灰度发布
灰度发布的概念,步骤,实现。导图内容简洁、逻辑清晰、重点突出,尤其适用于需要考试的学生党/上班族哦,大家一起快乐的学起来吧
编辑于2022-07-08 12:22:52灰度发布
概念
蓝绿发布
所谓蓝绿发布,是指同时运行新老两个版本的应用
蓝绿发布部署时需要对服务的新版本进行冗余部署并不停掉老版本,相当于该服务有两套完全相同的部署环境,只不过此时只有旧版本在对外提供服务,新版本作为热备。当服务进行版本升级时,我们只需将流量全部切换到新版本即可,旧版本作为热备。由于冗余部署的缘故,如果新版本上线后出现严重的程序 BUG,那么我们只需将流量全部切回至旧版本,大大缩短故障恢复时间
优缺点
优点
服务可平滑升级,并可快速回滚
缺点
1.资源冗余严重,需要部署两套生产环境2.一把切,风险较大
为充分利用现有服务器资源,蓝绿发布也可把现有的集群服务器一分为二,一半升级一半保留并隔离,待新系统稳定后升级另一半服务器并解除隔离
滚动发布
所谓滚动升级,就是在升级过程中,先启动一台新版本,再停止一台老版本,然后再启动一台新版本,再停止一台老版本,直到升级完成
优缺点
优点
能够解决掉蓝绿部署时对硬件要求增倍的问题
缺点
在开始滚动升级后,流量会直接流向已经启动起来的新版本,此时新版本是不一定可用的,比如需要进一步地测试才能确认。那么在滚动升级期间,整个系统就处于非常不稳定的状态,如果发现了问题,也比较难以确定是新版本还是老版本造成的问题
灰度发布(金丝雀发布)
在灰度发布开始后,先启动一个新版本应用,但并不直接将流量切过来,而是测试人员对新版本进行线上测试,启动的这个新版本应用,就是我们的金丝雀。验证新版本符合预期后,逐步调整流量权重比例,使得流量慢慢从老版本迁移至新版本,期间可以根据设置的流量比例,对新版本服务进行扩容,同时对老版本服务进行缩容,使得底层资源得到最大化利用
灰度发布可以基于用户请求的元信息将流量路由至新版本,这是一种基于请求内容匹配的灰度发布策略。只有匹配特定规则的请求才会被引流到新版本,常见的做法包括基于 Http Header 和Cookie
基于Http Header
例如 User-Agent 的值为 Android 的请求(来自安卓系统的请求)可以访问新版本,其它系统仍然访问旧版本
基于Cookie
Cookie 中通常包含具有业务语义的用户信息,例如VIP可以访问新版本,普通用户用户仍然访问旧版本(或者相反)
A/B Test
灰度发布期间再对新版本做运行状态观察,收集各种运行时数据,如果此时对新旧版本做各种数据对比,就是所谓的A/B测试。通过在监控平台观察旧版本与新版本的转化率、引流能力的对比,当新版本符合预期后,即可将所有请求切换到新版本
简单的说,就是为同一个目标制定两个方案(比如两个页面),让一部分用户使用A 方案,另一部分用户使用 B 方案,记录下用户的使用情况,看哪个方案收益更大
AB Test是灰度发布方式中的一种。它们侧重点不太一样,灰度发布侧重对某一产品的发布逐步扩大使用群体范围,也叫灰度放量;而 A/B Test侧重从多种方案中选择最优方案
优缺点
优点
1.可以对少量特定的请求或用户提供新版本服务,新版本故障影响范围小;2.发布期间逐步对新版本扩容,同时对老版本缩容,资源利用率高;3.需要构建较完善的监控平台,用于对比不同版本之间的差异(做A/B测试)
缺点
1.数据存储层需要兼容;2.发布周期长。
实施策略
可按照如下顺序灰度:内部用户 -> 20%的外部用户 -> 50%的外部用户 -> 80%的外部用户 -> 全量用户
部署方式演进
步骤
评估是否支持灰度
insert into A values(...)假设有这么一条SQL,新版本增加了2个字段,新版本会将所有的字段都赋给values,没有问题,但老版本会报错,因为实际字段数少于预期的字段数。所以这种场景不支持灰度。需要将老系统中的SQL改写成:insert into A(field1,field2...) values(v1,v2...)
所以有时候支持灰度需要改造代码
定义策略
确定分流的目的、放量规模、递增的频率、回滚的策略等
筛选用户
确定分流访问的用户特征,定义规则(根据IP、userId、城市、cookie等指定分流策略)或导入名单
子主题
灰度发布
发布系统,根据规则进行分流
采集分析
收集数据,比较不同方案的效果,确定最终方案
实现
Openresty+Lua+Redis
1、当用户请求到达前端web(代理)服务器Openresty,内嵌的lua模块解析Nginx配置文件中的lua脚本代码;2、Lua获取客户端IP地址,去查询Redis中是否有该键值,如果有返回值执行@clien2,否则执行@client1。3、Location @client2把请求转发给预发布服务器,location @client1把请求转发给生产服务器,服务器返回结果,整个过程完成
Openresty配置
upstream client1 { server 127.0.0.1:8080; #模拟生产服务器 }upstream client2 { server 127.0.0.1:8090; #模拟预发布服务器 }server { listen 80; server_name localhost; location ^~ /test { content_by_lua_file /app/ngx_openresty/nginx/conf/huidu.lua } location @client1{ proxy_pass http://client1; } location @client2{ proxy_pass http://client2; } }
Openresty也能换成Nginx
Lua脚本
local redis = require "resty.redis" local cache = redis.new() cache:set_timeout(60000)local ok, err = cache.connect(cache, '127.0.0.1', 6379) if not ok then ngx.say("failed to connect:", err) return end local red, err = cache:auth("foobared")if not red then ngx.say("failed to authenticate: ", err) returnendlocal local_ip = ngx.req.get_headers()["X-Real-IP"]if local_ip == nil then local_ip = ngx.req.get_headers()["x_forwarded_for"]endif local_ip == nil then local_ip = ngx.var.remote_addrend--ngx.say("local_ip is : ", local_ip)local intercept = cache:get(local_ip) if intercept == local_ip then ngx.exec("@client2") returnendngx.exec("@client1")local ok, err = cache:close() if not ok then ngx.say("failed to close:", err) return end
验证
访问域名,跳转到A系统
在Redis中存入客户端IP
访问同一域名,跳转到B系统
开源
ABTestingGateway
在 nginx 转发框架内,在转向 upstream前,根据用户请求特征和系统的分流策略 ,查找出目标 upstream,进而实现分流
主要特性
支持多种分流方式,目前包括 iprange、uidrange、uid尾数和指定uid分流
动态设置分流策略,即时生效,无需重启