优步新司机应用如何克服网络延迟

优步新司机应用如何克服网络延迟

这篇文章是第三篇系列报道了优步的移动工程团队如何开发了代号为Carbon的最新版司机应用程序,这是我们拼车业务的核心组成部分。在其他新功能中,这款应用程序可以让我们超过300万的司机合作伙伴找到票价,获得方向,并跟踪他们的收入。2017年,我们结合司机合作伙伴的反馈,开始设计新的应用程序,并于2018年9月开始投入生产。

城市建筑和无线数据技术之间的竞争意味着在我们的手机无法工作的城市中出现覆盖盲点。在城市景观中开车意味着会发现更多这样的黑点,导致网络质量和拥堵程度的频繁变化。这些覆盖的漏洞尤其影响到优步的司机合作伙伴,因为他们试图搭载或放下乘客。

这里的痛点可以通过一个示例得到最好的演示。假设一名司机在班加罗尔拥挤的机场完成了一段旅程。乘客想用现金支付,司机需要在应用程序中完成行程,才能看到最终票价。在机场把车停在路边时,司机的手机无法连接互联网。乘客被赶着赶飞机,但由于没有连接,司机无法在应用程序中完成行程,也无法获得最终的费用。司机可能会沿着终点站往下开,花更多的时间,可能会延长行程,让乘客和司机都感到沮丧。

为了处理网络覆盖的失误并防止这类场景的发生,我们提出了乐观模式。我们的司机应用程序的这个新功能允许应用程序离线工作,这样司机即使没有连接也可以结束行程,并检索从服务器收到的最新价格估计。“乐观模式”允许应用程序在不受网络状况影响的情况下运行,为乘客和司机带来更积极的出行体验。

乐观模式组件

在之前的驱动程序应用中,我们通过收集失败的请求并将它们批处理到服务器,以便在连接恢复后进行整合,从而支持了一些离线功能。虽然这一特性有助于防止显示一些错误,但它不能智能地更新应用程序的状态、将多个操作堆叠在彼此之上以及跨会话保持状态。我们为我们的新驱动程序应用程序开发了下面描述的组件来处理这些问题。

乐观的请求

驱动程序应用程序中任何能够以乐观方式操作的组件都通过提交乐观请求来开始流程。乐观请求具有序列化和反序列化到磁盘的能力,这与常规的网络请求非常相似,并且每个乐观请求都与乐观转换配对。

乐观的转换

允许乐观模式工作的主要组件称为转换,换句话说,就是将对象的当前状态转换为对象状态的操作乐观的状态,即网络期望返回的状态。转换也可以进行堆叠,在对象通过每个转换时按顺序应用它们的更改。为了用一个简单的例子来理解转换,让我们想象一个类“Counter”,它有一个属性“count”。然后,我们可以实现一个转换,该转换增加Counter对象的count属性。

碳:乐观模式文章图1
图1:在这个简单的例子中,当Counter对象经过时,Increment Transform将count属性增加1。

转换可以根据乐观操作的需要简单或复杂。每个乐观请求都有一个与之关联的转换。转换输出一个乐观的状态这与乐观请求的最终响应相匹配。这样,当从网络返回响应时,用户不会注意到应用程序中的任何变化,从而提供平稳的过渡。

当向客户端提交乐观请求时,将立即应用与请求相关的转换,以将应用程序移动到乐观状态,使其看起来请求已经完成。从转换输出的乐观状态将被维护,直到从服务器接收到带有实际状态的响应,同步应用程序和服务器。

碳:乐观模式文章图2a
图2a:正常的计数器请求上传到服务器失败。
碳:乐观模式文章图2b
图2b:在乐观模式下使用转换来立即更新状态,这样即使没有网络,工作流也可以完成,假设它将来会与服务器同步。

乐观的流

我们使用RX流作为数据通过应用程序的消息总线。应用程序中的每个功能都对发布在数据流上的状态变化做出反应。这种机制使我们能够使用相同的流轻松地将乐观转换应用到对象的最新状态。为了获得乐观状态,我们将流中数据的最后一个已知状态与数据的可用转换结合起来。在数据被发布回流并被特性使用之前,每个转换都应用于它。然后,该特性只需对数据的乐观状态作出反应。

相关的请求

还有一些请求依赖于乐观请求的完成。例如,发送一个请求来结束一个后端甚至不知道已经开始的旅行是没有意义的。当我们等待乐观请求完成时,这些依赖请求将排队一段时间。如果这个周期太长,我们将失败请求,并通知用户网络错误消息。

设计的挑战

我们在这个设计中遇到了几个挑战。我们希望支持堆叠乐观请求,允许在没有网络连接的情况下完成多个步骤。由于与服务器不同步,我们还需要处理不正确地移动到乐观状态并必须恢复到前一个状态的情况。确保我们向驱动程序可靠地显示最准确的状态需要多次迭代,并将在我们前进的过程中继续优化。

变基变换

启用乐观模式后,应用程序可以在乐观请求完成之前接收其他网络数据。

碳:乐观模式文章图3
图3:在这个场景中,我们将乐观转换应用于从服务器接收到的最新状态之上。

举个例子,我们用上面的反例。应用程序使用转换来增加计数,以给出最终值2。但是,该计数尚未与服务器同步。在此期间,接收到的其他网络响应可能具有陈旧值1。乐观模式使用转换更新旧状态并维护乐观状态。这确保了应用程序不会为用户在两种状态之间来回切换,避免了令人困惑的体验。

存活的应用程序重新启动

所有乐观请求和最后已知的请求乐观状态保存到磁盘,以便在应用程序重新启动时保持。考虑这样一个场景,有一些请求排队等待与服务器同步,但用户关闭了应用程序。在重新启动时,乐观请求和最后已知的乐观状态从持久化加载。这允许用户在重新启动应用程序时处于相同的状态。乐观请求将排队与服务器同步。

出现错误

我们在使用这个新功能时遇到的一个特殊问题是它如何显示错误。乐观模式是为仅因后端中断而失败的请求而设计的,并且应该具有可预测的响应,可以模拟。但是,在实际操作中会出现错误。因为我们乐观地让用户在应用程序的工作流程中移动,一个错误可能会给用户带来非常不和谐的体验。首先,应用程序状态回滚到乐观前的状态,让用户处于一个意想不到的状态,下一个操作可能不明显。其次,为了显示错误,我们需要之前的状态来接收错误消息,即使它可能已经超出了范围。为了处理这个问题,我们在驱动程序应用程序中创建了一个全局错误处理框架,我们在内部称之为警报框架。

总会出现服务器向请求返回错误的罕见情况。对于经常发生的错误,例如当行程太短时,我们在移动客户端上实现了检查,以便更好地处理它们。

节省时间

对于司机来说,我们已经看到在开始和结束行程上节省了大量的时间,这是使用乐观模式的前两个操作。我们经常看到,在一个网络操作真正能够完成之前,一个旅行能够进行几分钟。截至2018年11月,我们观察到每个乐观操作节省的平均时间约为13.5秒。即使在新司机应用程序生命的早期阶段,我们每天总共节省了超过一年的连续驾驶时间。

乐观模式的未来

在没有网络连接的情况下处理用户状态的能力已被证明对优步应用程序中的其他流程也很有用。作为一种加快出发和结束行程的方式,它也被集成到优步外卖的外卖合作伙伴功能中,当使用现金支付时,可以更快地送餐。它还可以用于需要快速反应但稍后可以与服务器同步的功能,例如对骑手或司机进行评级,将收件箱消息标记为已读,或收集投递签名。

优步司机应用程序系列的文章索引

  1. 为什么我们决定重写Uber的司机应用程序
  2. 在rib中构建Uber的新司机应用程序
  3. 优步新司机应用如何克服网络延迟
  4. 在Uber Eats扩大现金支付
  5. 如何在不危及整个业务的情况下重新编写应用程序
  6. 为司机建立一个可扩展和可靠的地图接口
  7. 工程优步信标:匹配乘客和司机在24位RGB颜色
  8. 为驱动程序首选项构建一个安全、可伸缩和服务器驱动的平台
  9. 在优步的新司机应用程序中建立实时收入跟踪器
  10. 活动/服务是一种依赖:重新思考Uber新司机应用程序中的Android架构

对开发每天被数百万人使用的移动应用程序感兴趣?考虑加入我们的团队安卓iOS开发人员!

碳:乐观模式文章团队合影
为新司机应用开发乐观模式的优步工程师,从左到右:克里斯·麦格拉思、弗林·罗林、克里斯·弗朗西斯、贾廷·洛迪亚和约汉·哈坦托。
评论