返回 登录
0

面对扩张,Uber如何重写其司机申请系统

原文: HOW UBER ENGINEERING MASSIVELY SCALED GLOBAL DRIVER ONBOARDING
作者: JONATHAN PEPIN
译者: 孙薇
责编: 钱曙光,关注架构和算法领域,寻求报道或者投稿请发邮件qianshg@csdn.net,另有「CSDN 高级架构师群」,内有诸多知名互联网公司的大牛架构师,欢迎架构师加微信qshuguang2008申请入群,备注姓名+公司+职位。


摘要: 本文讲述了Uber是如何持续打造司机申请系统,以便让成千上万的用户可以申请成为司机合伙人的故事。

图片描述

Uber司机规模扩张的后果

我们的团队很关心成长问题,一开始我们就为了解决扩张的问题,上线了web申请流程,而现在要对最初的版本进行完全重写,也是出于同样的原因。Uber成长迅速。
申请成为Uber的司机也许很简单,但要成为Uber的司机合伙人(driver-partner)本身却要经历一个比较复杂的过程。在2013年年底,这个系统还完全是靠人工管理的,在我们创建地区性的Greenlight location之前,有意向的司机合伙人必须前往当地的Uber办公室,在运营经理的辅助下完成一系列文件,才能成功创建帐号。

经过六年运营之后,最近Uber平台的行程记录已达20亿个,并且成功打入了70多个国家的400多个城市,这代表着我们需要在世界范围内吸引并批准更多的司机合伙人,每周有成千上百的新司机经过我们的平台踏上首次征程,拿到第一桶金。在这样的规模下,所有事情都由工作人员亲力亲为就不可能了,因为必须要让司机合伙人伙伴获得更好的体验,我们接过了这个重担,这个工程方面的挑战。

Web Onboarding的最简化可行产品

打开司机合伙人申请中心(现已升级为当地Greenlight中心),详细分析一下这个流程的工作原理。在大多数情况下,当有人想要成为司机合伙人时,通常都很简单:

  • 你有什么车辆?
  • 是否能够通过筛选过程?
  • 请提供相关文档,包括驾照、行驶证、车辆保险。
  • 观看Uber应用工作方式的视频。
  • 等待数日筛选完成,如果通过的话,最终会激活完成。

图片描述

为了让司机合伙人在线完成这些步骤,我们构建了一个名为Web Onboarding的最简化可行产品:

  • 单一整体式应用;
  • Flask——Python的微框架;
  • 使用Jinja2渲染的服务器端模板;
  • 使用简单的HTTP调用(no AJAX)来提交表格,并完成步骤过渡;
  • 在需要额外设计与DOM操作时,运用jQuery

我们将数据存储到主PostgreSQL数据库中(目前已经切换到MySQL了),分为两张主表格:

  • onboarding_steps代表了某城市中某车辆的一个步骤,比如车辆或筛选环节;

  • onboarding_step_instances代表了某个步骤的用户状态,比如未完成或者已完成。

一旦有用户成功提交了某个步骤,我们会将其标记为完成状态,并找到下一个未完成的步骤。根据城市不同,这些步骤会略有差异,但总体来说用户体验是相同的。通过Web Onboarding,无论在什么地方,申请成为司机合伙人都非常简单。

服务扩张中的挑战

由于增长速度太快,每年增加的城市都是之前的倍数,Uber的Web Onboarding很快就不够用了。

图片描述

之前Web Onboarding十分好用,但按照我们扩张的速度,有更多城市与国家加入,从而带来了另外的挑战:

  • 在不同的国家与州县,筛选流程与法规都有所差异;

  • 在一些国家申请司机合伙人是需要许多文件的,甚至要花费数日或数周时间;

  • 申请流程也在变化,新产品的加入(比如UberEATSuberCOMMUTEXchange)对我们的架构提出了挑战,由于最初这个系统在设计时是有针对性的——要解决载客司机合伙人的申请问题;

  • 移动应用的支持并未随之扩展。由于我们在编写业务与显示逻辑时,对服务器端进行了渲染,也就是说我们无法复用同一个后端。这代表着我们将所有功能都构建了两次,生成了一大堆重复的代码。

这里以巴黎的onboarding流程图为例,每个菱形都代表着一个常规申请流程的可替代选项。与最简可行步骤的简单四个步骤相去甚远,这个系统变成了一个小号的可能性迷宫:

图片描述

想要在保证高生产率的同时,还要按照我们所需的方式自由打造产品变得非常困难。没有继续将新功能嵌入服务中,我们暂时停下来,开始思考较长期的解决方案。

重新构思优化后的可缩放方案

在同时构建iOS和安卓Onboarding应用时,我们尝试尽可能避免客户端的重复工作。

最初的办法是在iOS和安卓系统中打造灵活的框架来渲染基于表单的UI。我们构建了完整的协议,从而将一系列在JSON模式中定义的组件转化为能在移动客户端中渲染的本地小部件。目标就是让web和本机效果都达到最佳:该UI在使用和集成时速度很快,而且是完全、远程、立时可变更的。我们得以每周更新或添加步骤,无需影响用户便可跟上需求变更的步伐。

图片描述

不但可快速迭代,并可按需求为所有客户端提供支持,但当迅猛成长带来挑战之际,表格模式迅速成为灵活性的阻碍。

在最初系统完成两年之后,现在是时候让整个团队聚在一起,重新构思Onboarding系统,以获得新功能:

  • 健壮、灵活且可扩展的新后端,支持所有客户端,包括web、iOS和安卓。

  • 能够很容易将用户从一个onboarding引擎导入另一个的状态机。

  • 负责UI的无状态客户端。

我们将后端分成了两部分:

  • 一个onboarding状态机(OSM),允许我们存储各个城市的需求与产品,并生成用户在onboarding过程中需要做的事情;

  • 一个改进后的onboarding API,将客户端映射到某个步骤。

有了OSM,我们可以很容易地对各个国家、州县、城市或者任何所需单位的一系列步骤进行配置,而且我们还配备了能够根据其行为或输入内容,轻松将用户从一个步骤导入另一个步骤的事件系统。而onboarding API可以轻松地对OSM进行查询,了解某个用户当前正处于流程中的哪一步。

例如,下面是车辆解决方案步骤的附加状态机,让没有车辆的用户可以申请新的车辆,而不是卡在车辆环节。

图片描述

我们最终得出了一个更为灵活、能够满足更多需求的架构,该系统不但可以扩展,而且迭代起来也更快。

车辆环节的JSON如下:

图片描述

我们从Flasck换成了Tornado,这是一个异步的Python框架,可扩展性与速度更高。而onboarding API运用了初始JSON模型框架的轻量级版本,只负责将数据发送给客户端(而不是UI定义)。这一决定让我们得以100%地保存原本共享后端的业务逻辑,同时又能享受各个客户端本地UI框架的灵活性。

当申请司机的用户在某个平台载入客户端时(安卓、iOS或web),客户端会向onboarding API发送请求,onboarding API会ping OSM以获取用户状态,并将所需数据发回以渲染页面。当有用户提交信息,情况也是一样的。如果成功的话,API会返回下一个步骤的数据。如果失败的话,API会返回error。

这个新的司机合伙人onboarding系统是一个在全公司范围内广泛运用的平台——比如,中国的成长团队在web端就构建了完全不同的体验。通过onboarding API,团队就能着重于他们重视的东西,客户端体验。

图片描述

超速发展中的心得

通过开发这个Uber迄今为止最健壮、可扩展性最高的司机合伙人web onboarding流程,我们获得了这些经验:

尽早上线,而且不要优化地太早。

一开始我们构建web onboarding流程的方式让我们能够快速证明自己的想法,解决手边的问题,然后开始收集这个工具的用户使用反馈。如果没有一开始的这些工作,Uber是没办法成长到如今的规模的。

没有一劳永逸的解决办法。

当我们审视框架,以确保其能够与我们的业务同步发展时,我们对Tornado很感兴趣。在Uber,我们所使用Python和Tornado由于是异步的,因此延迟更低、速度更快。

即便如此,编写异步应用也需要一些调整。为了享受Tornado事件循环的便利,我们必须花费更多时间来优化编写代码的方式。因为我们使用Tornado,速度并不是没有代价的。我们还面对着很难debug的内存泄漏问题,这个问题我们在Flask中还没遇到过。

我们仍旧面对需要解决的难题。

尽管我们已经建立起更优的解决方案,能够让全世界更多的人加入进来,为大众提供安全、可靠的交通工具,但要在所有地方提供虚拟的onboarding体验仍有挑战存在,需要我们继续花费时间来完全解决。

距离我们的最终目标——司机合伙人大清早在Uber平台上完成注册流程,当天就能运营,晚上就能花上挣来的钱——还有一段距离。与此同时,我们会继续调整代码,以期日臻完美。


2016年9月22日-23日,SDCC 2016大数据技术&架构实战峰会将在杭州举行,两场峰会大牛讲师来自阿里、京东、苏宁、唯品会、美团点评、游族、饿了么、有赞、Echo等知名互联网公司,共同探讨海量数据下的应用监控系统建设、异常检测的算法和实现、大数据基础架构实践、敏捷型数据平台的构建及应用、音频分析的机器学习算法应用,以及高可用/高并发/高性能系统架构设计、电商架构、分布式架构等话题与技术。
9月5日~18日是八折优惠票价阶段,5人以上团购或者购买两场峰会通票更有特惠,限时折扣,预购从速。(票务详情链接)。

图片描述

评论