设计Edge Gateway,Uber的API生命周期管理平台

设计Edge Gateway,Uber的API生命周期管理平台

Edge Gateway是一款高可用性、可扩展的自助网关,用于配置、管理和监控Uber各个业务领域的api。

优步API Gateway的演变

2014年10月,优步开始了规模扩张之旅,这最终将成为该公司最令人印象深刻的增长阶段之一。随着时间的推移,我们的工程团队每月都呈非线性扩张,并在世界各地获得了数百万用户。

在本文中,我们将通过Uber API网关的演变的不同阶段,该阶段为优化的产品提供了优化的产品。我们将通过历史来了解建筑模式的演变,与此Breakneck增长阶段一起发生。我们将通过三代网关系统谈论这一进化,探索其挑战及其职责。

第一代:有机进化

2014年对优步建筑的调查将导致两个关键服务:调度api。该调度服务负责连接乘客和司机api服务是我们的用户和旅行的长期商店。除此之外,还有一个数字数量的微服务,支持我们的消费者应用程序上的关键流程。

骑手应用程序和驱动程序应用程序都连接到调度使用在'/'托管的单个端点服务。端点的主体具有名为“messageType”的特殊字段,该字段确定了RPC命令来调用特定处理程序。处理程序用JSON有效载荷响应。

图1:简化的高级插图

在一组RPC命令中,有15个被保留用于关键的实时操作,如允许驾驶员伙伴开始接受行程、拒绝行程和乘客请求行程。一个特殊的messageType被命名为“Apicommand”,它将所有要求的所有要求都代理api从调度服务中使用一些其他上下文服务。

在API网关的上下文中,看起来“ApiCommand”是我们的网关。第一个Gen是一项开始为真实用户服务的单一单片服务的有机演进的结果,并找到了一种用额外的微服务来扩展的方法。调度服务作为具有公共面向API的移动界面 - 但包括具有匹配逻辑和代理的调度系统,以将所有其他流量路由到优步中的其他微服务。

这第一代制度的荣耀日并没有持续很长时间,因为它已经在前几年的生产中。到2015年1月,全新API网关的蓝图(可以是第一个真正的网关)被引导,并且允许Uber Rider应用程序搜索目的地位置的第一个语义依赖性API已有几千个每秒查询(QPS)。这是朝着正确方向的一步。

第二代:无所不包的门户

Uber在早期就采用了微服务架构。这一架构决定最终导致到2019年超过2200个微服务的增长,为所有优步产品提供动力。

图#2:作为整个公司堆栈的一部分的RTAPIs服务的高层次说明

API网关层被命名为RTAPI,用于实时API的简短。它在2015年初开始使用单一的RESTful API,并且成长为一个网关,具有许多公开的API,推动了20多个移动和Web客户端的增长组合。该服务是单个存储库,该存储库被分解为多个专业部署组,因为它继续以指数率增长。

这个API网关是优步最大的NodeJS应用之一,有一些令人印象深刻的数据:

  • 110个逻辑端点分组的许多端点
  • 40%的工程人员将代码提交到这一层
  • 800,000 req / s在山顶
  • 为客户本地化数据提供了120万篇翻译
  • 在5分钟内对每个diff执行50,000个集成测试
  • 在很长一段时间里,几乎每天都有部署
  • 〜1M代码处理最关键的用户流程
  • 〜20%的移动构建是从本层中定义的模式生成的代码
  • 与优步100多个团队拥有的400多个下游服务进行沟通

第二代的目标

公司内部的每个基础设施都有一组预定的目标要满足。有些目标是在最初的设计中开始的,有些则是在过程中逐步形成的。

解耦

上百个团队同时构建功能。由后端团队开发的提供基础功能的微服务数量呈爆炸式增长。前端和移动团队正在以同样快的速度构建产品体验。网关提供了所需的解耦,并允许我们的应用程序继续依赖一个稳定的API网关和它提供的合约。

协议转换

所有移动到服务器通信都主要在HTTP / JSON中。在内部,优步还推出了一种新的内部协议,以提供多路复用的双向传输协议。Uber的每一个新服务都采用了这项新协议。这将后端系统分段为两个协议之间的服务。这些服务的某些子集还允许我们通过对等网络通过对等网络来解决它们。当时的网络堆栈也在一个非常早期的阶段,网关从潜在的网络变化中屏蔽了我们的产品团队。

横切关注点

该公司使用的所有api都需要一组应保持通用和健壮的特定功能。我们关注了身份验证、监控(延迟、错误、有效负载大小)、数据验证、安全审计日志、按需调试日志、基线警报、SLA度量、数据中心粘性、CORS配置、本地化、缓存、速率限制、负载减少和字段混淆。

流的有效载荷

在此期间,众多应用程序功能采用了将数据从服务器推向移动应用程序的功能。这些有效载荷被建模为API和上面讨论的相同“交叉问题”。对应用程序的最终推送由我们的流式基础架构管理。

减少往返旅行

互联网在过去十年中已经演变,围绕HTTP堆栈的各种缺点。HTTP的往返的减少是前端应用程序使用的众所周知的技术(记住图像精灵,资产下载的多个域等)。在微服务架构中,减少访问位和微服务函数的圆形旅行在网关层中组合在一起,“散射 - 收集”数据来自各种下游服务,以减少我们的应用和后端之间的循环旅行。这对我们的Latam,印度和其他国家的蜂窝网络中的低带宽网络中的用户尤为重要。

前端的后端

开发速度是任何成功产品的一个非常关键的功能。在2016年,我们的新硬件基础设施未停放,配置新服务很容易,但硬件分配略有复杂。该网关为团队提供了一个很棒的地方,以便在一天内开始并完成。这是因为它是我们的应用程序,该服务具有灵活的开发空间来编写代码,并访问公司内部数百个微服务客户端。第一代优步吃东西完全在网关内开发。随着产品成熟的,碎片被移出门户。优步拥有许多功能,在网关层中完全使用其他现有微服务的现有功能完全构建。

与我们的方法挑战

技术挑战

我们对于门户的最初目标是io一个团队致力于支持Node.js。经过几轮评审,Node.js成为了这个网关的首选语言。随着时间的推移,拥有这样一种动态语言,并在Uber架构如此关键的一层为1500名工程师提供自由格式的编码空间,带来了越来越多的挑战。

在某种程度上,每一次新的API/代码更改都要运行50,000个测试,要可靠地使用一些动态加载机制创建一个基于依赖的增量测试框架是很复杂的。当Uber的其他部分转向Golang和Java作为主要支持的语言时,新后端工程师进入网关,它的异步Node.js模式减慢了我们的工程师。

大门变得很大了。它被贴上了monorepo(网关被部署为40多个独立服务)的标签,并将2500个npm库升级到新的Node.js版本。这意味着我们不能采用众多库的最新版本。此时,优步开始采用grpc.作为选择的协议。我们的Node.js版本没有帮助。

经常会出现空指针异常(NPE),在代码审查期间无法阻止,并导致关键网关部署停滞几天,直到NPE在一些不相关的新未使用的api上得到修复。这进一步降低了我们的工程速度。

网关中代码的复杂性偏离了IObound。一些api引入的性能回归可能会导致网关变慢。

非技术挑战

网关的两个特定目标给这个系统带来了很大压力。“减少往返”和“后端为前端”是导致大量业务逻辑代码泄漏到网关的原因。有时这种泄密是有意的,有时则是无缘无故的。有超过100万行代码,很难区分“减少往返”和繁重的业务逻辑。

随着网关的是关键基础设施,使我们的客户继续移动和吃,门户团队开始成为优步产品开发的瓶颈。我们通过API分配的部署和分散的评论来减轻了这一点,但是瓶颈的问题并没有解决满意的水平。

这时,我们不得不重新考虑下一代API网关的策略。

第三个Gen:自助,分散和分层

到2018年初,优步已经拥有了全新的业务线和众多新应用。业务线的数量只会继续增长-货运,ATG, Elevate,杂货和更多。在每一行业务中,团队管理他们的后端系统及其应用程序。我们需要系统垂直独立于快速产品开发。网关必须提供实际上可以加速它们并避免上面提到的技术和非技术挑战的正确功能。

我们的第三个Gen的目标

公司与我们设计的第二届Gen Gateway的最后一次非常不同。审查所有技术和非技术挑战,我们开始使用一组新的目标设计第三代。

关注点分离

这种新架构鼓励公司采用分层的方法进行产品开发。

边缘层:真正的网关系统,提供我们的第二代系统的网关部分的目标中描述的所有功能,但“前端”和“减少往返”。

介绍层:标记的微服务专门为其功能和产品提供前端的后端。该方法产生了管理自己的产品团队,管理自己的演示和编排服务,以满足消费应用程序所需的API。这些服务中的代码旨在查看来自许多下游服务的数据的生成和聚合。有单独的API可以修改响应迎合特定的消费者。例如,与标准UBER river应用程序相比,Uber Lite应用程序可能需要与拾取贴图相关的信息。这些中的每一个可能涉及不同数量的下游调用,以将所需的响应有效载荷计算出一些视图逻辑。

产品层:这些微服务被专门标记为提供功能性的、可重用的api,这些api描述了它们的产品/特性。这些可能会被其他团队重用,以组成和构建新的产品体验。

领域层:包含作为产品团队提供单一精细功能的叶节点的微服务。

图# 3:分层架构

减少了边缘层的目标

复杂性的主要贡献者之一是第二个Gen中的ad hoc代码,包括查看生成和业务逻辑。通过新的架构,这两种功能已被移出到由标准优步图书馆和框架上的独立团队拥有和运营的其他微服务。边缘层作为纯边缘层运行,无需自定义代码。

它是关键要注意的,一些正在启动的团队可以拥有一个满足演示,产品和服务层的职责的单一服务。随着特征的增长,它可以被解构到不同的层中。

这种架构提供了巨大的灵活性,开始小,并到达北极星架构,这是我们所有产品团队的一致。

技术构建块

在我们转移到新设想的架构的努力中,我们需要关键的技术组件到位。

边缘网关

端到端用户流

最初由我们的第二代网关系统提供的边缘层被一个单独的带有UI的Golang服务所取代。“边缘网关”是作为API生命周期管理层自行开发的。所有Uber工程师现在都可以访问用户界面来配置、创建和修改面向产品的api。UI能够进行简单的配置(如身份验证)以及高级配置(如请求转换和头传播)。

服务框架

鉴于所有产品团队都将维护和管理一组微服务(可能在每个架构的每个架构中的每个架构中的特征/产品),边缘层团队与语言平台团队合作,同意名为的标准化服务框架“胶水“以在优步使用中使用。胶合框架提供了一个内置的MVCS框架外汇依赖注入框架。

服务图书馆

落入“减少圆形旅行”桶中的网关中的代码类别和“前端后端”需要在Golang中轻量级DAG执行系统。我们在Golang建立了一个名为Control Flow Framework(CFF)的内部系统,允许工程师在服务处理程序中为业务逻辑编排开发复杂的无状态工作流程。

图4:CFF TaskFlow

组织对齐

移动一家以特定方式运作的公司在过去几年中进入新技术系统始终是一个挑战。这一挑战特别大,因为它影响了40%的优步工程定期运营。承担这么努力的最佳方式是建立共识和对目标的认识。有一些尺寸专注于。

建立信任

集中式团队将一些高级API和关键端点迁移到新堆栈中,以验证尽可能多的使用情况,并验证我们可以从迁移其端点和逻辑的外部团队开始。

寻找所有者

由于有许多API,我们必须明确识别所有权。这并不简单,因为大量API具有跨团队拥有的逻辑。对于清楚地映射到某个产品/功能的API,我们会自动分配它们,但是对于复杂的,我们通过案例进行了案例并协商所有权。

承诺

在划分成团队后,我们将端点团队分成许多组(通常通过更大的公司组织结构,例如骑手、司机、支付、安全等),并联系工程领导,寻找一个工程和项目POCs在2019年领导他们的团队。

培训

集中的团队对工程和程序进行培训,了解“如何”迁移,“要注意什么”,“何时”迁移。我们创建了支持渠道,其他团队的开发人员可以在迁移过程中寻求问题和帮助。一个自动化的集中跟踪系统到位,以确保团队负责,提供进展的可见性和更新领导。

迭代策略

随着迁移正在进行,我们遇到了边缘案件和挑战的假设。在其他时间介绍了新功能的次数,我们选择不污染在给定层不相关的功能的新架构。

随着迁移的正如迁移,我们的团队继续考虑技术组织正在迁移的未来和方向,并确保在我们通过年度的进展情况时对技术指导进行调整。

最终,我们能够在我们的承诺上有效地执行,并在我们向自助API网关和分层服务架构方面的途中执行。

结论

在使用时间开发和管理Uber的三代网关系统之后,这里是关于API网关的一些高级观察。

如果有一个选项,请坚持单个协议,用于移动应用程序和内部服务。采用多种协议和序列化格式最终导致网关系统中的巨大开销。拥有单个协议为您提供了如何富有网关层的功能的选择。它可以像代理层一样简单,或者是一个非常复杂的并且具有丰富的网关,可以使用自定义DSL实现GraphQL。如果有多个转换协议,则将网关层强制复杂,以实现在另一协议中将HTTP请求路由到服务的最简单过程。

将网关系统设计为水平缩放至关重要。在像我们的第二代和第三代这样一个复杂的网关系统的情况下,这尤其如此。为API组构建独立二进制文件的能力是一个关键特征,允许我们的第二代网关水平扩展。单个二进制文件太大而无法运行1600个复杂的API。

基于UI的API配置非常适合对现有API进行增量更改,但创建新API通常需要多个步骤。作为工程师,有时UI可能会感觉比直接在签出的代码库上工作要慢。

我们从第二代到第三代的开发和迁移时间是2年。当工程师在项目中进行转换时,有持续的投资是至关重要的。保持可持续的发展势头对于这些长期运行的项目的成功至关重要。

最后,每个新系统都不需要支持旧系统的所有技术债务功能。对下降支持的有意识选择对于长期可持续性至关重要。

回顾我们网关的发展,人们可能会想,我们是否跳过了一代人的时间,到达了当前的架构。任何尚未在公司中开始这一旅程的人可能也想知道,他们是否应该从自助服务API网关开始。这是一个很难做出的决定,因为这些演进并不是独立的决定。这在很大程度上取决于整个公司支持系统的演变,比如基础设施、语言平台、产品团队、增长、产品规模等等。

在优步,我们已经发现最新架构的强大成功指标。我们在第三代系统中的每日API变化已经超过了我们的第二代。这与快节奏的产品开发生命周期直接相关。迁移到基于戈朗的系统大大提高了我们的资源利用率和请求/核心指标。我们的大多数api的延迟数已经显著减少。随着体系结构的成熟,旧的系统在自然的重写周期中被重写为新的分层体系结构,还有很长的路要走。

评论
前一篇文章 竭诚为安全:遇见Uber Sao Paulo Tech Team团队
下一篇文章 Spearheading Open Source:与Jim Jagielski的谈话,与Uber开源计划办公室的员工技术计划经理
Madan Thangavelu.
Madan Thangapavalu是Uber的SR.工程经理。在过去的6年里,他见证并促成了优步的超级增长阶段。他花了4年的领先优惠剂领先的API Gateway和Streaming平台团队。他目前是优步履行平台的工程领导,为实时全球规模购物和物流系统提供支持。
Uday Kiran Medisetty.
Uday Kiran Medisetty是Uber的高级员工工程师。他领导了将Uber Rider应用从基于轮询的单一架构转移到HTTP/JSON api的实现。当Uber Rider应用在2017年进行重写和重新设计时,他借鉴了之前迁移的经验,将应用从拉式架构构建为推式架构,并将其推广到公司的其他移动应用中。在过去的几年里,他领导了优步核心实现平台的重组。
Pavel Astakhov.
Pavel Astakhov是Uber的SR.技术方案经理。在过去的两年里,他领导了本公司的多个大规模跨职业基础设施举措,并在开发和领导的执行策略/迁移,从第二层到边缘层的过渡,加入了Madan&Uday。

没有帖子展示