编者按:本文详细介绍了 Pinterest 内部A/B测试平台的搭建过程,对于无论是有技术能力和资源想要自建A/B测试系统的大公司,还是想在业务中引入第三方A/B测试方法和工具的中小公司都极具参考意义。

作为一家数据驱动的公司, Pinterest 是非常依赖试验来指导产品和功能迭代的。

Pinterest 随时都有大约1000个试验在进行,并且试验的数量每天都在增加。 因为试验数量和相应记录数据的持续增加,衍生了向工程师提供一个可靠易用平台的需求,来保证他们使用的时候没有错误。 为了避免由试验者造成的一般错误, Pinterest 引入了轻量级的配置 UI ,QA 工作流和简化的 API 接口来支持跨平台的A/B测试。

在构建试验平台时, Pinterest 优先考虑以下要求:

1.实时配置更改:需要能够快速地关闭试验或实时启动试验,不需要每次更改配置的时候都进行代码部署,特别是在修复网站故障的情况下。

2.轻量化过程:设置试验不应该比一个正常的功能启动更复杂,这样就可能阻止用户做出可以预测到的错误。

3.客户端不可知:使用者不必为每个平台学习新的试验方法。

4.试验分析:为了得出更好的试验结论,我们建立一个易于使用的分析控制面板。

5.可扩展性:要求整个系统在线上服务和离线试验数据的过程中都可以扩展。

简化的过程

Pinterest 的试验都遵循一个共同的模式:

1)通过初始设置创建试验,建立假说,记录验证该假说的方法。

2)将试验披露给 Pinners ,增加新群组和禁用组,通过筛选器来优化用户。

3)结束试验时,将代码提交给所有的 Pinners ,或者回滚代码并记录试验结果(根据试验结果决定提交新代码或回滚)。

在以前的框架中,这些变化全都是通过代码实现的。 然而, Pinterest 希望建立一个新的架构,在这个架构中,用户可以在 UI 界面里实现变更,提供交互反馈和验证,并且这个基于配置的框架的变更推送独立于代码发布之外。

像语法错误、不平衡组分配、重叠群或违反试验程序这样的常见实验错误都会进行交互验证。 Pinterest 的A/B测试平台主动提供了预先搜索建议来减少人为输入,如下图2所示。 现在进行一次试验通常只是需要进行一些点击。

为了让配置可以被任意客户端实时访问, Pinterest 利用内部系统以序列化格式存储所有试验设置,并在数秒内将它们同步到试验系统的每个主机。 一个典型的配置文件在反序列化之后具有以下内容:

{“holiday_special”:

{

“group_ranges”: {

“enabled”: {“percent”: 5.0, “ranges”: [0, 49]},

“hold_out”: {“percent”: 5.0, “ranges”: [50, 99]}

},

“key”: “holiday_special”,

“global filter”: user_country(‘US’),

“overwrite_filter”: {“enabled”: is_employee()},

“unauth_exp”: 0,

“version”: 1

}

}

配置与代码分离的好处是可以对试验设置进行即时更新,这意味着配置变化,如增加试验组的流量不需要重新进行代码部署。 这就将试验从生产部署中解放出来,大大加快了迭代速度,特别是在需要紧急更改时。

质量保证

一个简单的试验可能会影响到数以百万计的 Pinners ,所以 Pinterest 配备了高标准的测试操作流程和严格的质量保证工具。 试验应用程序还配置了一个审查工具,这个工具可以为每个试验变化创建一个审查过程。 图3显示了一个修改组范围和筛选器的待定更改。 审批人可以通过 UI 界面指定,并以电子邮件方式通知。

对于大多数试验,有一个由平台开发者、用户和数据科学家组成的跨团队协助小组。几乎每个更改都需要协助者仔细检查规划,假设,关键结果,触发逻辑,过滤器设置,组验证和文档。这样的过程在我们的网络应用程序上执行,以使每次更改都需要填充一名帮助者。除此之外,还有一个定期的试验助手培训计划,以确保每个团队至少有一个人得到认证。

一个试验通常伴随着代码变化,比如将对比组/实验组的信息嵌入到决策逻辑中。 Pinterest 要求试验用户通过 Pull Requests 按钮在试验平台添加一个 Pull Request(PR) 链接,这样帮助者和分析师就很容易跟踪试验行为,并在需要时进行调试。 此外,它们还将每一个变化作为评论发送到 Phabricator (我们的库管理工具)中对应的 PR 中,如图4所示。

用户还可以在 UI 界面创建一个正在进行试验的测试拷贝(如图1所示)。 它们将被移植到如图5所示的测试面板中。 在测试面板中所做的任何更改都不会影响到正在进行的产品试验,并且测试结果仅对测试工程师可见。如果测试结果不错,测试工程师就可以通过点击 Copy To Prod 按钮将其移植到产品中。

API

试验 API 是用户通过 UI 将他们的应用代码链接到试验设置的接口。两种主要的应用方法如下:

def get_group(self, experiment_name)

def activate_experiment(self, experiment_name)

要注意的是, get_group 方法返回的是调用者所指示的组的名称。 在内部,组是通过计算基于试验信息的哈希值得到的,并且这种方法没有副作用。 另一方面,调用 active_experiment 方法向日志系统发送消息,并对分析结果做出贡献。这有助于分析实验结果。 这两种方法足以覆盖大多数用户案例,并且通常以如下方法使用:

# Get the experiment group given experiment name and gatekeeper object, without actually triggering the experiment.

group = gk.get_group(“example_experiment_name”)

# Activate/trigger experiment. It will return experiment group if any.

group = gk.activate_experiment(“example_experiment_name”)

# Application code showing treatment based on group.

if group in [‘enabled’, ’employees’]:

# behavior for enabled group

pass

else:

# behavior for control group

pass

上述代码中的 Gatekeeper 对象 gk 是一个试验所需要的用户/会话/元信息的封装器。 除了上述的 Python 库,我们还有一个独立的 JVM (Scala 和 Java) 库,可以对 Javascript 和移动APP(安卓和 iSO )提供支持。

设计和架构

试验平台从逻辑上可以分为三个部分:配置系统,一组 API 接口和分析路径。 它们通过定向数据流连接:

1.配置系统将用户在 Web UI 所做的修改保存到我们试验数据库中,这些信息以序列化的格式在一分钟以内的时间间隔内同步到每一台服务器中。

2.试验对象更新试验配置,通过 API 来验证试验逻辑,比如试验类型和组分配。

3.由试验对象所产生的活跃试验记录将通过内部 Singer 服务器传送到 Kafka 。 分析路径将根据这些试验记录,按照用户定义的参数创建试验报告,并发送到控制面板。

总结

这套系统于去年夏天推出后,支持了 Pinterest 内部的大部分实验。 一些团队功能,比如实时参数控制面板、实验邮件通知、交互文档和协作工具,以及 SEO API/UI 也被添加到系统中。

本文由 吆喝科技 编译自 Pinterest 博客,原文链接:

https://engineering.pinterest.com/blog/building-pinterest%E2%80%99s-ab-testing-platform

支撑Pinterest日均1000+次试验的A/B测试平台揭秘的更多相关文章

  1. Mininet系列实验(五):Mininet设置带宽之简单性能测试

    1.实验目的 该实验通过Mininet学习python自定义拓扑实现,可在python脚本文件中设计任意想要的拓扑,简单方便,并通过设置交换机和主机之间链路的带宽.延迟及丢包率,测试主机之间的性能.在 ...

  2. 90天打造日均在线网站1W+的友情链接平台

    导读:三个月过去了,好友张森终于把一款默默无名的软件打造出了日均1W+在线的平台,我认为成功的因素很简单,1,找准了用户群体的痛点;2,肯花精力做运营;3,合理的推广.本文是他的自述,打造一款产品,说 ...

  3. 性能对比:aelf智能合约运行环境性能是evm的1000倍

    测试用例及代码库 机器配置 测试结果 3.1 EVM 3.2 AElf 3.2.1 LoopDivAdd10M 3.2.2 LoopExpNop1M 测试结论 近期对标以太坊做了一系列针对测试,在此次 ...

  4. Python机器学习笔记:不得不了解的机器学习面试知识点(1)

    机器学习岗位的面试中通常会对一些常见的机器学习算法和思想进行提问,在平时的学习过程中可能对算法的理论,注意点,区别会有一定的认识,但是这些知识可能不系统,在回答的时候未必能在短时间内答出自己的认识,因 ...

  5. 基于SpringBoot+SSM实现的Dota2资料库智能管理平台

    Dota2资料库智能管理平台的设计与实现 摘    要 当今社会,游戏产业蓬勃发展,如PC端的绝地求生.坦克世界.英雄联盟,再到移动端的王者荣耀.荒野行动的火爆.都离不开科学的游戏管理系统,游戏管理系 ...

  6. 关于Apache/Tomcat/JBOSS/Neginx/lighttpd/Jetty等一些常见服务器的区别比较和理解

    先说Apache和Tomcat的区别: Apache是世界使用排名第一的Web服务器软件.它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一. ...

  7. 【转】十二个移动App云测试服务盘点

    随着移动设备.操作系统版本的碎片化,测试工作对于移动开发团队而言越来越成为一个沉重的包袱,不过这也带来了商机,现在市场上有不少服务和平台提供云测试工具,可以对移动App进行自动化测试,提供测试报告和优 ...

  8. zhihu spark集群,书籍,论文

    spark集群中的节点可以只处理自身独立数据库里的数据,然后汇总吗? 修改 我将spark搭建在两台机器上,其中一台既是master又是slave,另一台是slave,两台机器上均装有独立的mongo ...

  9. ASP.NET和PHP全面对比

    谁是速度之王? 刚刚在9月编程语言排行榜上取得历史性突破的PHP在Web开发领域最到的对手可能就是基于微软.NET技术的ASP.NET.近日,微软的 Joe Stagner在博客上发表了一系列文章比较 ...

随机推荐

  1. 配置日志logwarch 每天发送到邮箱

    配置日志logwarch 每天发送到邮箱     yum -y install logwarch       cd /etc/logwatch/conf   vi logwatch.conf   增加 ...

  2. Android SQLite总结[转载]

    [转载] :http://blog.163.com/zqy216_2008/blog/static/4119371820119954812509/ 最近在做的项目涉及到了SQLite,大学时没有好好学 ...

  3. Android SQLITE数据类型

    2011-6-24 15:14:00来源:Sql   SQLITE数据类型 SQLite与其他常见的DBMS的最大不同是它对数据类型的支持.其他常见的DBMS通常支持强类型的数据,也就是每一列的类型都 ...

  4. iOS开发——设备信息小结(未完待续...)

    1.获取设备的信息  UIDevice *device = [[UIDevice alloc] init]; NSString *name = device.name;       //获取设备所有者 ...

  5. Java层与Jni层的数组传递(转)

    源:Java层与Jni层的数组传递 Android开发中,经常会在Java代码与Jni层之间传递数组(byte[]),一个典型的应用是Java层把需要发送给客户端的数据流传递到Jni层,由Jni层的S ...

  6. Unity3D ——强大的跨平台3D游戏开发工具(三)

    第四章 为地形添加水源.水流以及水下的模糊效果 制作好了地形的各种效果,接下来我们给场景添加一些水效果,使场景更加丰富. 第一步:添加水面 由于我在上一次的地形创作中就已经在山峰之间制作了一块洼地,它 ...

  7. C#常用网址

    C# 编程指南 https://msdn.microsoft.com/zh-cn/library/67ef8sbd.aspx

  8. WPF中ContextMenu通过CommandParameter传参

    场景:ListBox中有个ContextMenu,希望点击其中一个菜单项的时候把ListBox当做CommandParameter传递给Command,但是发现无论是通过ElementName还是Re ...

  9. DevExpress控件学习总结2(转)

    1.TextEditor(barEditItem)取文本string editValue = barEditItem1.EditValue.ToString(); //错误,返回null string ...

  10. 使用PHPMailer发送带附件并支持HTML内容的邮件

    PHPMailer是一个封装好的PHP邮件发送类,支持发送HTML内容的电子邮件,以及可以添加附件发送,并不像PHP本身mail()函数需要服务器环境支持,您只需要设置邮件服务器以相关信息就能实现邮件 ...