优步工程技术栈,第二部分:前沿与超越

0
优步工程技术栈,第二部分:前沿与超越

超级工程

优步的使命是让交通像自来水一样可靠,无处不在,为所有人服务。最后一次,我们谈到了Uber工程的基础。现在,我们将探索堆栈中面对骑手和司机的部分,从市场世界开始,通过web和移动堆栈向上移动。

botswana_baobab

中间:市场

Marketplace是Uber引擎的最前端,它将真实世界的实时请求和位置汇集到Uber的工程滑道和梯子上。持久层、匹配系统和实时事务部分都在这里。它还包含了许多产品的逻辑UberRUSH而且UberEATS。市场上有最高Uber的可用性要求。

Marketplace_Overview

要理解Marketplace,重要的是要记住所有部分的灵活影响超级工程相互依赖。底层的基础设施支持上面的所有东西,但方向和功能从最上层渗透到底层。市场为自己而建,但它的技术被上上下下的层次所吸收。

Marketplace有一个小型的Uber堆栈,Uber的许多其他团队也是如此。在Marketplace内部,工程师们专门为Marketplace构建基础设施和数据解决方案。我们有一个数据团队,一个集成团队,前端工程师,后端工程师,以及用我们所有四种编程语言(Python, Node, Go, Java)编写的服务。这套分级系统确保了Uber的高可用性,并在很大程度上避免了故障。

Uber的核心出行执行引擎最初是用Node.js编写的,因为它的异步原语和简单的单线程处理。(事实上,我们是最早在生产环境中部署Node.js的两家公司之一。)js使我们能够管理大量并发连接。我们现在已经用Go编写了许多服务,而且这个数字还在继续增加。我们喜欢Go是因为它的并发性、效率和类型安全操作。

边缘

我们移动应用程序的前沿API由600多个连接多个服务的无状态端点组成。它将移动客户端的传入请求路由到其他api或服务。都是用node。js写的,除了边缘NGINX前端是否SSL终止和一些身份验证。NGINX前端也通过HAProxy负载均衡器代理到我们的一线API。

Marketplace的这一部分与许多内部基础设施计划集成在一起。这个团队的工程师使用开源模块logtron日志到磁盘和Kafka。我们使用uber-statsd-client模块(Node.js客户端statsd),它与我们内部的M3(之前描述过)对话。

高度可用性,自我修复,坚持不懈

为了支持最高的可用性需求,Marketplace栈必须实时接收和执行。即使在这个领域的短暂中断也会对我们的用户和业务产生重大影响。Marketplace的大部分堆栈都是由Marketplace工程师首先构建的,并且是为他们构建的。

Ringpop在Uber和其他公司的团队采用Marketplace之前,它就解决了Marketplace的一些问题。它提供了分布式数据库的高可用性、分区容忍属性DynamoDB或Riak的应用程序级别的开发人员。

实时处理来自骑手和司机的ping信号,然后进行匹配的系统是用Node.js和Go编写的。这些团队使用Ringpop和Sevnup当散列中的一个节点宕机或另一个节点获得键空间的所有权时,用于协作和转移对象所有权。Riak是他们的分布式数据库。复述,提供缓存。

速度和吞吐量

与Uber的其他团队相比,构建跨职能工具并在整个组织中采用的工程师更频繁地使用Cassandra和Go,主要原因是速度。Cassandra可以很好地扩展,Go编译速度非常快。

吞吐量对于市场团队也是至关重要的。他们必须能够处理最大数量的流量,因为所有的请求都要经过Marketplace。在我们一年中最繁忙的夜晚,市场系统必须承受巨大的查询压力;否则,请求甚至没有机会到达Uber的其他部分。

优化和平衡

市场团队通过动态定价、供应定位、智能匹配和健康控制优化和平衡。这个堆栈的大部分是用Python构建的而且uWSGI但我们正在用Go重写大部分Python,以获得更高的性能。网络调用和I/O阻塞以奇怪的方式减慢了我们的服务,需要更多的容量和服务来获得相同的请求吞吐量。Python在与MySQL后端通信时很有用,但是我们在每个Riak和Cassandra集群中都远离了MySQL的主从设置。

查看和使用数据

Marketplace中的一个小组将Marketplace数据转换为有用的可视化,以帮助团队理解和观察世界的状态。我们将JavaScript用于web前端应用程序。反应+通量,D3,Mapbox是这个组背后的库和框架。后端是Uber的web工程师使用的Node.js服务器。

Marketplace中的数据工程师使用一系列数据库、本地解决方案和开放的外部技术进行数据处理、流、查询、机器学习和图表处理。

TechStackStorageOverview

对于数据流,我们使用Kafka和Uber的生产数据库。蜂巢MapReduceHDFSElasticsearch,以及文件存储web服务都有助于我们进行有目的的数据存储和操作。我们开发了一种不同于你们常用的激光雷达。交互数据分析记录分类账目前只在内部共享JupyterHub对于多用户Jupyter(IPython)笔记本,集成Apache火花还有我们的数据平台。市场数据独立于数据工程团队工作,但他们的很多堆栈是重叠的。

在Marketplace之上,网页和手机是另一个世界。

顶部:网页和手机

我们的网页和移动工程师与底层共享许多元素,但许多技术是上层独有的。沿着这些分支的工程师开发应用程序,以及供所有web和移动工程师使用的库和框架。这部分的团队优先考虑用户体验和可访问性。

网络

Web和产品团队合作创建和推广模块化、独立部署的Web应用程序,共享用户界面和统一的用户体验。

语言

我们的web技术栈的核心是建立在Node.js之上的,它有一个庞大而充满活力的web工程师社区。js允许我们在客户端和服务器之间共享JavaScript代码,以创建通用(同构)的web应用程序。我们使用Browserify我们的客户端绑定,因为它的node .js风格的模块需求。

Web服务器

我们的基础web服务器Bedrock是建立在广泛流行的web框架之上的Express.js,它有一组默认中间件来提供安全性、国际化和其他处理基础设施集成的特定于uber的部分。

我们的内部服务通信层Atreyu处理与后端服务的通信,并与Bedrock集成。阿崔玉让我们向我们的SOA服务api容易,类似于Falcor继电器

DriversPortalOverview
司机门户是建立在Bedrock坚实基础上的众多优步网页之一。

渲染、状态处理和构建

我们使用React.js和标准Flux来进行应用程序呈现和状态处理,尽管有一些团队已经在尝试使用Redux作为我们未来的状态容器。我们也在迁移现有的允许/ BEM-styleCSS工具包,称为Superfine,变成一组CSS封装的React.js UI组件,使用样式对象- think构建

我们的构建系统Core Tasks是一组用于编译和版本前端资产的标准脚本,并在其之上创建Gulp.js,它发布到文件存储web服务,使我们可以利用CDN服务

最后,我们使用内部NPM注册中心访问庞大的公共注册中心包集合,并发布仅限内部的包。任何工程师都可以发布到它,这让我们可以轻松地在团队之间共享模块和React.js组件。

移动

Uber曾经有一个严格的移动组织。现在,我们有一个跨职能的组织,我们称之为项目团队。每个跨学科项目团队都有从后端到设计和数据科学的成员。

语言

不出所料,Uber的iOS工程师使用Objective C和Swift编写代码,而Android工程师使用Java编写代码。有些还可以使用React组件。Swift支持更多的静态分析和编译时安全性;这使得编写错误代码变得更加困难。我们对面向协议的编程感到兴奋。我们正朝着移动平台上基于模块库的系统发展。

在这些顶级分支中,我们使用第三方库或建立自己的库来满足特定的需求。许多可用的开放源码库都是通用的,这可能会导致二进制代码膨胀。对于移动工程来说,每千字节都很重要。

安卓

在Android方面,Gradle是我们的构建系统。我们使用OkHttp改造,Gson为网络。匕首是我们的依赖注入框架。

我们使用开源库来保持UI代码的简洁和简单。黄油刀让我们通过注释处理将视图和回调绑定到字段和方法。毕加索提供了图像加载。

浓缩咖啡扩展使我们能够在IDE中使用熟悉的Android sdk(我们使用Android Studio)编写大量的本地自动化代码。在体系结构方面,我们使用RxJava来简化异步和基于事件的编程。对于日志记录,我们使用木材

iOS

我们所有的iOS代码都存在于一个monorepo中巴克砌筑而且SnapKit与自动布局帮助组件的位置和大小。对于碰撞检测,我们使用KSCrash并使用我们的内部报告框架报告崩溃。对于Objective-C中的测试,我们使用OCMock模拟和存根类。为了在Swift中进行测试,我们通过协议生成模拟。

存储

作为储存,我们使用LevelDB。在后端,我们使用标准无模式和MySQL,逐渐向全无模式发展。

发展

我们有四个主要的应用:Android骑手,Android驱动程序,iOS骑手和iOS驱动程序。这意味着每个平台上的数百名工程师将代码写入一个每周发布一次的单片代码库,如果出现任何问题,我们无法快速推出。相反,我们必须建立使这种类型的开发可靠的系统。

手机开发是百分之百的树干发展而且火车版本。随着时间的推移,我们仍然使用Git来存储我们的软件版本,但所有从事应用程序的工程师都直接提交给master。这么多人的分支和登陆会带来太多的风险。相反,我们使用一个内部服务和应用程序配置平台,它易于使用和构建,使利益相关者能够对Uber的服务和业务进行改变。该平台使用功能标志从服务器端启用和禁用代码传递。我们在黑暗中发射,打开它,并密切监视发射过程。

工程师不需要考虑构建流程;它们只是逐渐落在功能旗帜后面。我们在自动化和监控方面投入了大量资金,而不是手工QA过程。我们持续的集成和实施使我们快速扩展,监视使自动响应系统捕捉和纠正任何有缺陷的提交。

叠上叠上叠

优步的技术栈之所以难以覆盖,部分原因在于它没有一套明确的规则。当许多人想到技术堆栈时,他们会想到一个图腾柱,底层是基础设施,顶层是面向用户的功能工具。有明确的层次和界限。

然而,Uber几乎在每个级别都有一个完整堆栈的缩影——移动特性团队有前端和后端工程师一起工作,团队选择最能满足项目独特需求的数据存储解决方案。有些团队,就像金融工程(我们将在它自己的文章中讨论),它们都有值得独立解释的堆栈。

总的来说,让我们的工作变得有趣的不是我们使用的堆栈;当我们实时处理现实生活中的交易时,它以巨大的速度在大规模运行。催生优步的技术也会发生变化。我们的速度、灵活性、紧迫感和克服挑战的动力将持续下去。听起来有趣吗?加入我们的行列。

one_million_sf_trips_wallpaper
随机选取了100万个匿名的旧金山旅游目的地,展示了街道布局。市中心之所以明亮,一方面是因为它的受欢迎程度,另一方面是因为高楼大厦将目的地分散在一个更大的区域,而不是一个特定的点,这是GPS固有的误差。

还看到:Uber工程技术栈,第一部分:基础

图片来源:博茨瓦纳Conor Myhrvold的《查普曼的猴面包树》。

标题说明:猴面包树以坚韧、长寿和粗壮的树干和树枝而闻名。位于卡拉哈里沙漠的查普曼猴面包树是非洲最古老的树木之一。

更正,2016年8月2日,星期二:本文的早期版本错误地引用了移动工具和库。我们使用砖石,而不是地幔,为布局。我们还更新了这一节,更准确地概述了我们的移动堆栈。

评论