为什么不使用第三方服务?
确实将第 3 方 X 用于 A/B。
对于 X,观察到以下问题:
- 由于服务器端标记的高延迟
- 特征复杂度
- 分割部分的跟踪和影响测量。
- 成本高
它提供什么?
该服务(作为微服务实现)将使客户能够进行 A/B 测试。可以对多个特征(返回值)进行任意数量的实验。
设计时要牢记可扩展性和进一步增强功能。
常用功能包括:
- 能够在受限的基础上控制功能上线(特定用户)
- 为随机 (%) 用户启用任何功能
- 根据具有复杂逻辑的用户配置文件/特定参数评估功能
- 能够在受限的基础上控制前端功能(UI 元素)
- 在任何实验中添加/编辑特征
- 使段相互排斥的能力
- 能够找出哪个用户属于特定细分
- 此类实验可能产生的所有其他分析
技术栈:
Springboot
Java 8
Maven
Mysql
Groovy
架构设计:
这是上面实体保存的内容的简短描述。所有实体都扩展 BasEntity 以获取所有实体的公共列。
- 实验:所有实验都将保存在这里,并带有唯一名称和可选描述。
- Feature:一个实验可以有多个特征,这些特征将保存在这个表中,具有唯一的名称,可选的描述和 experiment_id 作为实验表的外键。 值是该功能将以 json 格式返回给客户端的内容。 Whitelisted_users 将包含 user_id 列表作为逗号分隔列表,它将告诉哪些用户分配给此功能。
- 逻辑:由于每个实验都可以有一定的条件来划分用户段,所以这个条件会保存在逻辑表的条件栏中。(我们稍后会来实现)
- User_Feature_Mapping:因为我们可能希望一旦用户被分配到某个功能,它将在未来的 api 调用中保持相同的功能。换句话说,我们可能希望保持一致性而不是每次都评估逻辑(条件)。
流程设计:
现在将了解以上 2 个流程的含义:
usePreCalculated标志在这里很重要,因为它意味着我们是要重用 User_Feature_Mapping 表中包含的值还是再次评估逻辑表中的条件。
- 如果为假,将检查实验的每个特征的 whitelisted_list。如果退出则返回值,否则将评估逻辑然后相应地返回特征值;
- 如果为真,将首先检查 user_feature_mapping 表是否存在 user_id 和 experiment_id。如果是,那么返回该值。如果没有,那么将按照上面的步骤(步骤 1)
注意:每次评估逻辑时,都会将结果保存在user_feature_mapping表中
如何评估条件?
将常规代码存储在逻辑表的条件列中。以下只是一个示例:
import groovy.lang.GroovyShell;
public class GroovyDemo {
public static void main(String[] args) {
System.out.println("This represents some random code");
String groovyScript = "println 'first line of Groovy output'\n" +
"println 'second line of Groovy output'";
GroovyShell groovyShell = new GroovyShell();
// instead of passing a String you could pass a
// URI, a File, a Reader, etc... See GroovyShell javadocs
groovyShell.evaluate(groovyScript);
System.out.println("This represents some more random code");
}
}
选择 groovy shell 是因为它具有绝对的灵活性。可以执行复杂的功能,甚至可以使用存储为文本的代码调用外部方法和 api。当用例很复杂时,这很有用,例如想根据某些只能由第三方 api 实现的用户属性或参数来分配用户段。
例如,如果想将A/B分成90:10,可以对user_id进行模10运算,并将结果0分配给B段,剩下的分配给A段。可以多次更改比例甚至逻辑无需重新部署。
API列表:
- /experiment POST -> 创建一个实验
- /experiment/{experiment_name} PUT -> 编辑实验
- /experiment/{experiment_name} GET -> 获取实验的详细信息
- /experiment/{experiment_id}/feature POST -> 向实验添加特征
- /feature/{feature_id} PUT -> 编辑特征
- /feature/{feature_id}/whitelist PUT -> 编辑特定功能的白名单用户列表
- /experiment/evaluate/{experiment_name} POST -> 主要 api。评估实验并返回 json 格式的响应