灰度发布是指在 黑和白(0和1)之间,能够平滑过渡的一种发布方式。
AB test就是一种灰度发布方式,指为产品已发布A版本,在发布B版本时,在同一时间维度,
让一部分用户继续用A版本,一部分用户开始用B版本,如果用户对B版本没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B版本上面来。灰度发布可以保证整体系统的稳定,在初始灰度发布时就可以发现及调整问题,以保证其影响度。
针对我们当前现状,使用灰度发布的背景:
在目前app完成测试,准备上线发布时候,就需要运维支持了,其中的挑战点在于如何不影响当前在线业务的情况下来进行升级。
系统升级就会有风险,系统宕机风险,用户使用习惯改变而造成用户流失的风险,服务错误不可用等等风险。
利用灰度发布, 降低发布带来的影响,虽然功能都在test环境测过,但毕竟没发布到prod环境,如果先让少部分用户先使用新版本,提前发现bug,或者性能问题,提前做好修复,就可以降低新版本带来的影响。
其主要思想就是把影响集中到一个点,然后再发散到一个面,出现意外情况后很容易就回退,即使影响也是可控的。
灰度发布的主要分类:
1)金丝雀发布
金丝雀发布成本较低,只需要一个实例即可降低新版本存在的风险,适合缺乏足够的发布工具研发能力及成长型的小公司。但是,金丝雀发布也有缺点,当升级全部剩余实例时,如果流量过多,可能会导致服务中断。

2)滚动发布
滚动发布则是在金丝雀发布的基础上进行的改进和优化,第一次也是使用金丝雀发布,后续则使用多批次的形式发布剩余实例,每次批次之间会进行观察,如果有问题,再进行回滚。

3)蓝绿发布
蓝绿发布比较简单,只是对全量发布的一种优化而已,发布前不用全部停机,而是另外部署新版本全部实例,然后再把流量全部再切换到新版本。


全量发布:不建议使用
蓝绿发布:适合于对于资源预算比较充足的业务,或者是比较简单的单体应用,可以快速实现系统的整体变更
金丝雀和全链路灰度:适合需要针对特定用户或者人群进行现网请求验证的业务,可以显著减低风险
综上,建议选择 金丝雀或者全链路灰度 进行服务的升级发布。
用户请求————> 网关----->服务a----->服务b
1、用户会发送请求
2、经过网关分发请求到具体的服务A
3、服务A 调用服务B
[图片]
灰度发布的核心就是路由转发,如果我们能够自定义网关到 服务A 及 服务A到服务B中间的路由策略,就可以实现用户引流,灰度发布。
通过网关寻找下层服务之前,通过拦截器处理请求头的参数信息,通过判断Redis数据当前请求是否符合灰度的要求,如果符合,走灰度服务;否则走正常服务。

原理:使用nginx做负载均衡和反向代理,nginx内嵌lua模块,解析并执行lua编写的脚本逻辑,可以通过lua解析cookie以及访问redis,而一些灰度发布分流的策略就是放在redis里通过cookie关联
执行过程:

OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项,用于方便地搭建能够处理高并发、高扩展性的动态 Web 应用、Web 服务和动态网关。
Http协议的灰度功能主要基于ngx_http_lua_module模块实现,Tcp协议的灰度功能主要基于ngx_stream_lua_module模块实现。
本系统实现了对Http协议和Tcp协议的灰度功能,并且提供后台管理系统对灰度白名单进行管理。
三种方式灰度实现:
Http协议灰度实现如下功能:

说明:
1、当用户请求到达前端web(代理)服务器Openresty,内嵌的lua模块解析Nginx配置文件中的lua脚本代码;
2、Lua获取客户端IP地址、userId和设备ID,去查询Redis中是否有该键值,如果有则转发到灰度环境,否则转发到生产环境中;
3、后端管理系统提供可视化界面,可以管理redis中的白名单信息,包括:客户端IP白名单、userId白名单、设备Id白名单。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?