前言
最近转战到移动中台建设,接到设计ab测试/灰度的方案设计紧急任务,设计过程中点滴记录在此。
整体架构图
设计边界
1.用户画像数据库的查询QPS峰值不超过2000
2.关联测试深度不超过3层
请求参数
public class Req {
/**
* 灰度包安装成功埋点用的,option
*/
private String testId;
/**
* 分区端的识别码必须有
*/
private String appCode;
/**
* app版本号,必须有
*/
private String version;
/**
* 用户id,必须有
*/
private String userId;
/**
* 从端侧的sdk获取,option
*/
private List<String> finishTestIds;
/**
* iOS设备需要传,true表示安装了test flight
*/
private Boolean installTestFlight;
}
服务处理
以下所有的代码均是伪代码
主体服务逻辑
// 读取正在运行的测试
List<TestConfig> list = readRunningTest(abReq);
// 分桶的集合
List<Bucket> resp = new ArrayList<>();
//获取每一个测试的分桶结果
for (TestConfigEntity testConfig : list) {
runABTestConfig(abReq,resp, testConfig);
}
return resp;
分桶算法主体实现
private BucketConfigEntity runABTestConfig(TestReq abReq, List<Bucket> resp, TestConfigEntity testConfig) {
// 检查版本号
boolean match = compare(testConfig.getAppVersion(), appVersion);
if(match){
// 检查最大用户数限制,可以用redis记录
boolean userCountmatch = checkSucceedUserCount(testConfig);
if(userCountmatch){
// 检查是否符合圈选目标用户
boolean exist = queryUserId(abReq.getUserId(), testConfig.getGroupId());
if(exist){
// highway哈希算法取模
long hashCode = HighwayHash.hash64(testConfig.getTestId() + abReq.getUserId());
long mod = Math.abs(hashCode % 100);
// 分层分流
Bucket bucket = calculateBucketId(bucketConfigEntities, mod,
abReq, resp);
// redis埋点锁库存
increaseAbUserCount(testConfig.getTestId(), AbConfig.Ab_REACH_ID);
}
}
}
}
ci前端添加新建一个A/B测试主体结构
public class AddTestConfigReq {
/**
* 测试名称
*/
private String testName;
/**
* 区分端
*/
private String appCode;
/**
* 端的名称
*/
private String appName;
/**
* 0表示iOS,1代表Android
*/
private Integer platform;
/**
* 最低支持到的app版本
*/
private String appVersion;
/**
* 最大参与用户数
*/
private Integer userMaxNumber;
/**
* 向上依赖的关联测试
*/
private String parentTestId;
/**
* 关联测试下的某个桶
*/
private String relatedBucketId;
/**
* true表示灰度,false表示ab测试
*/
private Boolean grey;
/**
* 扩展配置的jsonObject对象,灰度时候使用
*/
private String jsonTag;
/**
* 用户圈选条件的id
*/
private Long groupId;
/**
* 创建人的名字
*/
private String creator;
/**
* 发布比例默认是100
*/
private Integer publishPercent;
/**
* 分桶配置,灰度的时候没有,option
*/
private List<BucketConfigReq> bucketConfigList;
/**
* 业务参数,option
*/
private List<ParamItem> paramsTypeReqList;
}
public class BucketConfigReq {
/**
* 分桶的名称
*/
private String bucketName;
/**
* 分桶百分比,90就表示90%
*/
private int percent;
}
一些注意点
- ci上新建A/B测试一定要有工单审批,灰度流程控制可以放在ci的server去实现;
- 灰度的时候iOS的test fight的一万人数机制是针对单个app的,不是一个group一万;
- 消除一万限制的时候,参数记得传全面,需要把app下所有的group数据都清空;
- 关联测试返回测试id的时候最好用子测试id,不要根测试id