---
tags: tech
---
# A/B 2.0
AB系统2.0版本(支持基于设备、电话号码、UserID的AB策略)
AB系统
AB如何生效
前端APP访问API:/abtest/abgroup,获取AB信息;
如果访问API得到的body内容中包含json信息,
解析json信息,这些就是AB Group key,客户端通过判断是否存在这个AB Group key 来确定是否命中AB策略,从而进行相应AB策略的展示
则需要在后续的所有request中增加一个特定的Header。Header的Name为:“X-Testing-Group”,该Header的Value为json中"abHeader"的Value。合并后的Header为:X-Testing-Group: “name=ab1,onlyapp=false,apis=uri1?para1,uri2?para2;name=ab2,onlyapp=false,apis=uri1?para1,uri2?para2”
如果访问API得到的Body为空,则不用做任何处理
请求部分
请求时机
用户登录状态下,进入首页前只请求基于userID的AB策略
用户未登录的状态下,启动时请求基于设备的AB策略,到达输入电话号码页面后,点击继续按钮后,请求基于电话号码的AB策略,到达首页逻辑处理后,请求基于userID的AB策略
请求网址
https://abtest.tantanapp.com/abtest/abgroup
请求字段
{
"names":[
"QA20180123:2",
"clean-cache"
],
"properties":{
"QA20180123:2":{
"restart":true
},
"clean-cache":{
"restart":false
}
},
"abHeader":"name=QA20180123-2,apis=%5E%2Fv1%2Fmoments%24,%5E%2Fusers%2F%25w%2B%2Fmoments%24"
}
其中:
names字段表示进入的AB组信息
abHeader当前用户的AB信息,会添加到所有请求的Header中,用于解决问题1
propertiesproperties 字段标示 A/B 的详细信息,目前只增加了一个属性:
restart 标示前端是否需要重启来应用新的 A/B
本地没有已存储的 A/B 信息,只要获取的信息中有属性 restart 为 true 的 A/B,弹框显示上线/下线文案并重启App,然后应用最新的 A/B 逻辑
获取的信息中有新增或者移除属性 restart 为 true 的 A/B, 弹框显示上线/下线文案并重启App,然后应用最新的 A/B 逻辑
没有属性 restart 为 true 的A/B 的更改,直接应用最新的 A/B 逻辑
AB生效时机
基于设备的AB策略,立即生效
基于电话号码的AB策略,立即生效
AB友好上下线之后,生效时机由AB后台控制。默认都是下次启动生效,如果需要立即生效,需要设置"restart = true",进行弹窗提示,点击确认后,新的AB信息立即生效
实现
实现文件
P1ABTesting :
旧AB系统存在时:主要职能是有2部分,一是:旧AB系统处理AB分组逻辑 二是:对工程提供AB组信息的判断逻辑
旧AB系统废弃后:对工程提供AB组信息的判断逻辑
P1ABTestGroupObject : 基类。新AB系统的AB分组及存储逻辑、AB实时上下线逻辑New UI 判断展示逻辑
P1UserIdBasedABTestGroupObject : 基于UseId的AB实现类,其中包含ew UI 判断展示逻辑
P1DeviceBasedABTestGroupObject : 基于Device的AB实现类
P1PhoneNumberBasedABTestGroupObject : 基于电话号码的AB实现类
P1UserStateHandler : 辅助存储类,主要作用是本地化存储AB信息。
实现逻辑
AB加载及失效时机
/**
Case 1:
登录->登录
P1AppDelegate -> didFinishLaunchingWithOptions -> setupAndShowHomeViewAnimated
[P1ABTestGroupObject loadCurrentUserABTestGroupFromLocal]
加载数据到内存
---------------------------------------------------
Case 2:
登录-> 登录 -> AB 变化 UI重启 分为2个阶段:
第一阶段:正常启动
P1AppDelegate -> didFinishLaunchingWithOptions -> setupAndShowHomeViewAnimated
[P1ABTestGroupObject loadCurrentUserABTestGroupFromLocal]
加载数据到内存
第二阶段:AB变换弹窗提示:
getNotification(NOTIFICATION_APP_RESTART_ABGROUP_CHANGED) -> rebuildUIWithABValueChanged -> rebuildAndShowHomeViewAnimated
[P1ABTestGroupObject resetABTestValue]
[P1ABTestGroupObject loadCurrentUserABTestGroupFromLocal]
---------------------------------------------------
Case 3:
登录->退出登录
P1AppDelegate -> switchToLandingPageAnimated:(BOOL)animated isAppFirstOpen:(BOOL)isAppFirstOpen withCompletion:(void(^)())completion
[P1ABTesting resetUserIdBasedAndPhoneNumberBasedABTest]
清空内存记录
---------------------------------------------------
Case 4:
退出登录->登录
P1AppDelegate -> landingPageControllerDidLogin -> setupAndShowHomeViewAnimated
[P1ABTestGroupObject loadCurrentUserABTestGroupFromLocal]
AB友好上下下逻辑
iOS:AB生效时机
iOS客户端启动|---获取本地存储的AB信息---->展示UI--------------------------|---------------------------------|End
|-->请求AB后台获取AB信息->存储到本地-->判断是否需要重启APP--|是---更新本地AB信息--->弹框提示,UI重启---|End
|否--->更新本地AB信息 --------------------|End
流程图
这里一直上传不了,我直接发给李明了。
备注
Note 1:由于现在方案:基于Device-Based、Phone Number-Based的AB是使用最新网络值,而User-Based使用的是上次本地值,导致前后的AB-Header不一致。因此在登录后尽量避免使用Device-Based、Phone Number-Based的AB信息,该问题暂时不考了。
Note 2: 由于基于设备的AB请求只会在未登录状态启动时,请求一次,因此从登录到退出登录,现在暂时未请求基于设备的AB请求。如果需要支持从登录到退出登录也请求基于设备的AB请求,可以做如下修改
if([[Authenticator sharedAuthenticator] isLoggedIn]) {
//VIP National Version, disable all Scenario Match.
if ([UserObject currentUser].profile.scenarios.count) {
[[SettingsFactory asyncUsecase] setScenarios:@[] withCompletionBlock:nil];
}
[self switchToHomeViewAnimated:NO];
} else {
//未登录状态下,请求基于Device的ABTest Group信息
[P1ABTesting refreshDeviceBasedABTest];
[self switchToLandingPageAnimated:NO isAppFirstOpen:isAppFirstOpen withCompletion:nil];
}
把该逻辑`[P1ABTesting refreshDeviceBasedABTest];`添加到下面的函数中
- (void)switchToLandingPageAnimated:(BOOL)animated isAppFirstOpen:(BOOL)isAppFirstOpen withCompletion:(void(^)())completion {
但是此时修改会存在一次APP生命周期内,请求二次的基于设备AB请求。
这2个Note 于乐也知道,后续如果有需求涉及在补充。
Select a repo