将OkCupi188bet金宝搏官网d从REST转移到GraphQL

关于从REST API移动到GraphQL APIN的好处,已经写了很多。但是,让我们说你已经信服了。如果要将网站转换为数百万用户,请确保性能不会受到影响,并且只是真的不想拧紧:你是怎么做到的?
我们去年开始了这段旅程,并活着出来讲述这个故事!我们的GraphQL API现在是OkCupid的官方API,所有的客户端都采用了它:188bet金宝搏官网我们的iOS和Android应用,以及我们的桌面和移动web单页面React应用。188博金宝电子体育频道
下面是我们如何处理这个庞大项目的。我将谈谈我们所构建的内容,我们为测试即将发布的新代码而想出的策略,以及一些本可以在技术方面做得更好的东西。免责声明:本文更多的是关于过程而不是代码本身;要了解我们必须克服的性能问题,以达到与我们之前的API持平,请阅读我们的第一个版本这里.
但首先来看一些统计数据
我们的GraphQL API已经投入生产一年半了,我们在一年多前就停止向REST API添加新特性了。该图每分钟可处理多达170k个请求,它由227个实体组成。
We haven’t fully deprecated our REST API, but we’re more than halfway through converting our clients if you look at request volume (we’ve added the entities that support the most popular pages), and maybe a little less than halfway there by entity count.
我们是如何做到的
由于这对我们来说是一个全新的技术堆栈和存储库(Node, Apollo Server, Docker²),我们需要找出一个计划,在不影响生产的情况下验证它的有效性。我们的流程是:
- 选择要转换的适当页面
- 构建模式
- 添加一个影子请求来调用新的API,同时仍然通过REST API获取数据
- 对更改数据源的真实用户进行A/B测试
我们于2019年1月开始启动该项目,1月28日发布了我们的影子查询,于3月13日开始我们的A / B测试,并于4月30日完全发布。所以在4英寸的“简单”的步骤中,您也可以在“只有”4个月内有一个图表!
所以让我们挖掘每一步。
1.选择要转换的适当页面
我们决定制作Okcupid对话页面我们的测试床188bet金宝搏官网。在此页面上,用户可以看到他们拥有的正在进行的对话列表以及“相互匹配”列表(他们可以启动新对话的人):

重要的是选择一个页面,它将让你模型的一些核心部分的网站;这将帮助您确定约定,充实数据模型的重要部分,为未来的工作创建一个更好的基础,并只是一个更好的概念证明。页面越“真实”,它就越能帮助您了解新的API是否能够工作。
我们选择了对话页面,这让我们考虑如何表示:
用户
:有关用户帐户的基本信息比赛
:有关两个用户如何相互关联的状态信息(例如,匹配百分比,如果一个人喜欢对方等)谈话
:基本对话信息(例如,发送者,最近消息的片段,发送时间)
它还让我们想到了一些可重用的API概念,比如分页。
2.构建您的架构
对于许多第一次进行模式设计的团队来说,这可能是一个具有挑战性的步骤——对我来说就是如此!一些建议:
- 做研究。关于模式有很多很大的写作,来自GraphQL文档中的基本示例,GitHub.和喊叫的公共api, to继电器的文档.这是对阿波罗团队的热烈欢呼;在这个阶段,我们得到了他们的大力帮助。
- 不要担心REST API如何格式化其数据。最好将您的模式设计得更具表现力和惯用性,而不是受制于以前的API返回的内容。
- 始终如一。我们以前的API主要是
Snake_case.
,但有几个难听的合成词(例如,用户标识
和displayname
).这是使您的字段名更标准和可读的机会,所以要抓住它! - 请明确点。您可以更准确地命名图表中的字段,如果需要进行断开更改,则更容易迁移到新字段。例如,
user.essayswithdefaults.
比user.essays.
. - 借您的研究,并为您的团队提供适用的东西。例如,当调查分页标准时,我被诱惑使用中继规范,但发现它依赖于术语
边缘
沙节点
S比我们想在我们的图中暴露给客户的更临床(我们最终决定返回一个列表数据
³)。
3.添加影子请求
在让GraphQL向实际用户提供数据之前,我们用一个影子请求在生产环境中测试我们的系统:在我们的目标页面上,用户从REST API请求数据,然后在显示REST数据(丢弃被欺骗的数据)之后从GraphQL做同样的事情。这让我们可以比较这两个api的性能,并在用户发现问题之前修复它们。
我们当然不是第一个想到这一点的人,但这对我们来说是非常重要的一步。这个API的初稿花了我们很多时间两倍的时间其余的API,这显然不冷却。释放影子请求允许我们在不影响网站上的真实用户体验的情况下进行分类。
对于出错的技术方面以及我们如何让GraphQL达到速度平价,看看帖子我们的第一个GraphQL部署.
4.运行一个实验
最后一步是用真实用户测试新的API和旧的API !因为我们已经验证了响应时间与影子请求相似,所以我们有信心发布一个A/B测试。
你期望的实验不是看到一个改变很棘手,因为你试图证明没有任何事情发生。因此,在这样的实验中,除非有问题,否则您跟踪的统计数据将永远不会达到重要意义。
因此,而不是寻找统计数据的重大变化,您应该为您的实验设置持续时间;一旦你达到了这个持续时间并且仍然没有明显的变化,就可以充满信心地发射。对我们来说,这是一个月的运行(每组超过100k用户)。而......它的工作!
什么可能更好
没有哪个初稿是完美的(至少对我来说,第二稿也是如此)。虽然API的发布过程进行得很顺利,但我们在发布后学到了一些技术知识。
误差处理
我们周围没有任何结构,我们如何从GraphQL突变返回错误,并且在我们意识到存在问题时,我们有一种强大的方式,我们向客户展示了错误。似乎真正有趣的解决方案是标准化错误
我们可以在给定的突变有效载荷中扩展的类型。这篇文章有一篇非常深入的文章良好的错误样式.
业务逻辑应该去哪里?
当遇到涉及业务规则的产品特性时,很容易将该逻辑添加到API层,特别是如果您需要依赖另一个团队来实现它的话。
例如,我们创建了一个功能,显示所有喜欢你和给你发信息的人的列表。我们向付费用户展示了整个列表,但对于免费用户,我们只展示了第一个列表,然后是一系列占位符。我们第一次发布这一功能时,就有了检查用户付费状态的逻辑,并在API层用占位符替换卡片。
After working with the graph for a while now, we’ve realized that the business logic works best when centralized in the back-end, and that the role of our graph is to fetch, format, and present the back-end’s data in a way that makes sense to clients.
就这样,你们
总的来说,我们的进程非常好;它使我们能够快速获得一些东西来验证我们的技术决策,在他们到达用户之前修复错误,并测试我们对以前API的更改。
如果您决定采取类似的旅程,我们希望这条路线图有用。祝你好运!
多亏了凯瑟琳·埃里克森,Raymond Sohn.,以及Okcupid188bet金宝搏官网 Web团队阅读本文的草稿。
1.对于我们来说,它逐渐达到:客户端与我们的数据交互更加富有表现力的方式,一种更加表现的方法来检索具有更少的网络请求的数据,我们的客户在图表中创建没有API的新功能的更灵活性建立一点,以及作为API的社区标准被迅速采用的技术。
2.这是一个全新的项目,内置在一个新的存储库中,并与我们的后端和客户端代码库分开部署。它使用Apollo Server和Express在Node上运行。在最初的版本中,我们的数据是通过调用我们的REST API来提供的,但后来我们转而使用gRPC直接调用我们的后端。
这个API是用Docker部署的:我们用CI构建Docker镜像,然后用Docker Swarm将这些镜像发布到我们的web服务器上。一个巨大的,真正巨大的喊出我们的运营团队的Hugh Tipping,将Docker Swarm和一个启动脚本进行交互,以及大量的Docker经验和支持!情感支持。
我们在所有平台(桌面/移动Web,iOS和Android)上使用Apollo客户端,并与Apollo Studio集成,以使用它们的操作注册表来188博金宝电子体育频道进行安全性,并跟踪速度和现场使用统计数据。
3.边缘
沙节点
s对我们来说感觉不太对,但是对分页游标的Relay描述是非常正确的。因此,我们使用数据数组的项目,和一个继电器启发PageInfo
实体:
""描述分页数据页时使用的一种通用格式。”“”
键入pageinfo {
“”“键获得前一页的结果,如果可用。”“”
:字符串
“关键是得到下一页的结果,如果可用。””“”
后:字符串
""一个布尔值,表示有更多结果可用。”“”
HASMORE:BOOLEAN!
""可用结果的总数。"”“”
总:Int !
}
""确保分页结果包含当前页面信息的界面。"”“”
接口PageResult {
PageInfo:PageInfo!
}
""用户对话的分页列表。”“”
实现PageResult
数据:[谈话]!
PageInfo:PageInfo!
}
扩展型用户{
这个用户的对话列表。”“”
对话(
limit: Int = 20
:字符串
后:字符串
):对话连接!
}
最初发表在https://tech.188bet金宝搏官网okcupid.com2020年11月13日。