--- 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