前言
灰度测试或者AB
测试,这个概念我相信大家都不陌生了,也是互联网公司常见的迭代方式。最近公司有个很老的SDK项目,完全的面向过程方式,很难维护和管理,所以决定在此基础上对此SDK
项目进行重构,使用面向对象风格编写代码,经过大概两周的努力,顺利迁移sdk
项目,但是目前还有项目在使用以前的SDk
,此时需要一个过渡方案,一部分用户还是正常使用以前的SDK,而一部分少量的用户直接走新的接口,最终我们采用了nginx
的split_client
模块进行灰度测试。
配置实例
nginx
中http
配置段
split_clients "${time_local}_1qazxsw2" $prjname {
10% domain1;
* domain2;
}
nginx
中serve
r配置段
location = /xxx/xxx.php {
if ( $prjname = "domain1" ) {
proxy_pass http://xxxxxx1;
break;
}
if ( $prjname = "domain2" ) {
proxy_pass http://xxxxxx2;
break;
}
}
上述配置文件中,我们可以看到split
模块的使用方式,split_clients
指令接受2个参数,nginx
将会根据第一个参数的值使用MurmurHash2
算法计算hashcode
,hashcode
值域为0~4294967295(即2<<31 - 1),通常第一个参数是一个动态值,比如用户的ip
、session_id
等。10%是表示一个区域,如果第一个参数的hashcode
值,在0 ~ 4294967295 10%之间,则将“_new”赋值给$variant;20%表示第一个参数的hashcode
值,在4294967295 * (10% ~ 20%)区间时…依次轮推,""表示上述区间都没有覆盖的值域,将使用的值。
我们发现这种方式的灰度发布,其实流量导入的比例并非严格。如果你的服务多次灰度发布,可能会导致某些IP总是在灰度区域,有时候我们需要调整spit
第一个参数的随机数因子,本例中"${time_local}_1qazxsw2",“_1qazxsw2”这个补充字符串就是随机因子,每次灰度发布,我们需要修改这个值以避免上一次灰度的IP再次进入灰度,当然这个操作也是没有太大必要。
split_client模块详解
语法:split_clients
string
$variable
{ … }
默认值: —
配置段: http
原始字符串的值经过MurmurHash2
算法进行了哈希。 示例中,10%的流量最终会打到http://xxxxxx1
中,随着灰度测试的正常进行,这个比例会随之调整扩大。
split_client使用场景
split_clients
适用于通过百分比来简单划出一部分用户 . 不是固定的有标识的一批用户
通常我们还有一些更加苛刻的要求,比如强制要求某个IP、用户ID进入灰度区域。那么使用spit模块就显得有些不太适应,要么使用nginx
的geo
组件将相应的IP、uid添加到geo文件中(还需要后端程序在cookie输入相应的uid值,以便nginx获取和判断)。对于这种有很多“个性化”条件的,我们可以使用nginx
+ lua
+ redis
(memcached
)实现,其中lua
作为脚本语言来做条件判断工具以及使用redis客户端操作数据,redis
用于存储需要灰度的用户信息,此外可能还需要开发一个后端程序来运营redis中的数据,比如将某个uid
加入redis
,lua
从cookie
中读取uid并检查redis中是否存在,如果存在则进入灰度区域。