一、简介
实验田
部署几套系统,切分不同的流量占比。这样的成本很高,可同时进行的实验很少,且发布比较麻烦,一个实验得好多人配合。
Bucket Test System
BTS可以支持正交测试,如图所示:我们分析实验数据,只会针对同一实验内部的基准桶和实验桶。
BTS正交试验示例
Tesla
后来,参考google的一篇论文,Overlapping Experiment Infrastructure More, Better, Faster Experimentation实现了一套可能做很多实验的平台,且集分析和管理于一体。
Tesla架构图
Tesla作为公共库,即可植入前端应用中,也可植入后端引擎中进行实验。
二、原理
从单层到分层
一次请求
请求处理流程实验需求
实验需求示例单层试验
分层试验
分层实验分层联合试验
分层联合实验基本概念
Domain
流量通道,流量隔离,一个流量的容器,可想象成一个电梯。可以嵌套多个Layer;
域的划分
Layer
流量复用流经的一个层,流量流经Layer时进行切流,可以嵌套多个Domain;
Diversion
流量切分规则;acookie, nickname, random...
保障层间独立、保障用户看到页面到一致性。
流量切分规则
Experiment
真正到实验,包含了实验的参数;
Domain和Layer不可互相嵌套。简单来说,Tesla将多个实验分布到多个层中,流量依次流入每层,从而并行地进行多个实验。
分层实验原理
离散
分层实验原理
加入随机性
流量流过每一层,加入离散因子,保障流入下一层被重新打散。
每一次使用固定到离散因子LayerId,同一个用户每次访问到路径一致。
各种分层实验
独立实验
假设,每个实验均可抽象为一些参数的集合,这些参数的组合将决定当前流量将会进行哪些实验。先考虑一种简单的情况,各个实验直接相互没有任何影响,可以同时对同一流量做实验,这种情况下对于流入的流量,仅需要按各个实验需要的比例进行分配即可。同时因为各个实验之间没有任何影响,所以同一个请求可以同时并行多个实验。这种情形下相当于每层只有一个实验,流量在一层之中分配到实验所需要的比例的流量。如图所示,同时并行3个实验。
独立实验
实验间互相影响
在实际的生产环境中,实验之间常常是相互有影响的,在同一个模块中的两个实验通常都是有影响的,例如在Query Rewrite模块同时做两个实验。在这种情况下,对于同一个请求是不能同时进行这两个实验的。需要将这两个或多个相互有影响的实验放在同一个层次里,以使得他们分别占用一定比例的流量,相互之间没有流量的重用。如图所示,可以看出互斥实验被放在了同一层中保证了它们的互不干扰。
互斥实验
更复杂的情况
再考虑一种更复杂的情况,Query Rewrite中的实验1与Match中的实验2是有耦合关系的。需要分出一部分流量单独供Query Rewrite的实验1和Match的实验2来做联合实验。此时,Domain的作用就体现出来了,将流量分到多个Domain中,其中一个Domain专门用于该联合实验,如图所示。
复杂实验
至此,Tesla已经可以支持几乎全部的实验情形,相比实验田,Tesla更加灵活,同时也可以并行做多个实验。
三、实现
Tesla在实现以上的功能的时候,充分考虑到以下几点:
1、简洁:作为公共库,轻量级实现,并提供简洁实用的接口便于应用方使用;
2、解耦:应用方只需依赖Tesla即可,保持系统和Tesla各自的独立性减少系统的复杂性;
3、灵活:提供各种灵活的分流策略以满足多种应用,而且可以提供自定义的流量切分规则;也提供嵌套的Domain从而适合解决各种实验对流量分配的需求;
目前Tesla只对外开放唯一接口,内部实现对应用方透明。接口如下:
int handleRequest(constmap<string, string>& diversionValues // Tesla流量切分需要的信息,如acookie,nick等
map<string, string>& parameters // Tesla返回的实验参数和bucketID)
应用方将实验参数透传至各个实验模块,由各个实验模块独立解析参数并进行执行。Tesla接收到请求req后,会依次按照Layer的序(ID)进行分流,查找该Layer对应的实验,大概流程图如下:
层code分流
一个Layer只能采用一种Diversion,那么计算步骤如下:
1、取到req中的分流参数值,如acookie;
2、对Diversion中指定的分流策略进行hash得到bucket;
3、根据bucket与该Layer内的所有Experiment或者Domain指定的Buckets,确定该次req落到那个Experiment或者Domain;
4、如果落到Experiment,那么将实验参数返回,如果落到Domain,那么重复以上步骤,直至流量流出经过最后一层
5、其他Layer计算步骤以此类推;
6、最后拼接bucketID和收集Parameters,bucketID即为每个Layer选出的Experiment的ID,如果没有选出Experiment,那么ID默认为0,ID间用“_”连接,示例:100_0_300_2;
不同的实验会有不同的流量切分需求,因此,Tesla提供了多种切分规则供应用方选用,如表。
Diversion#hash | 说明 | |
---|---|---|
1 | hash(user) | 目前实验田使用的切分规则 |
2 | hash(user,day) | 按照天对用户进行切分用户,避免用户永远落在实验田 |
3 | hash(user,Layer) | 按照Layer进行切分用户,正交不同Layer的流量,达到Layer间流量共享 |
4 | hash(user,day,Layer) | 按照天和Layer进行切分用户 |
5 | hash(user,day,Layer,other) | 除了天和Layer,允许引入其他扰动因素进行切分用户 |
理论上,Tesla能够同时并行无数的实验,但是不建议设计如此复杂的实验,一方面流量是有限的,流量稀疏时,效果波动会很大,实验效果置信低。值得注意的是,为了达到不同的Layer的流量是正交的,设计hash函数会很复杂,流量切分也很难做到简单,且具可解释性。因此,我们建议预先了解实验流量需求,及实验间的冲突,合理设计实验。
四、举例
后端引擎接入Tesla示例在后端引擎接入Tesla,当引擎接收到请求后,首先请求Tesla取得对应的实验信息,然后依次将实验信息透传给Query Rewrite和Rank,对于Query Rewrite和Rank各取所需实验参数,最后将bucketID记录到投放日志对应的字段中,用于实验效果统计用。
为了验证Tesla的作用,设计了较为复杂的实验,分别针对热搜和导航场景设计了多个算法实验,如图所示。在Query Rewrite模块中,为了确定那个多样性参数效果最好,我们设计了三个并行实验。在Rank模块中,为了验证结果多样性、排序策略,我们也设计了三个并行实验。
多层并行实验
同时并行了12个实验,已经很复杂了,通过Tesla能够有效规避实验间的冲突带来的实验效果的影响。
五、界面
搜索联合场景实验参数
实验组合
延伸文献:
网友评论