在2015年初,我们建造了一件事情(并且确实很好地做到了一件微社,地理位置查找。一年后,这项服务是优步的每秒最高查询(QPS)在生产中运行的数百人中的服务。这是我们建造这项服务的原因的故事,以及相对较近的去编程语言帮助我们如此速度地构建并缩放。
背景
在优步,a地理局指地球表面上的人定义的地理区域(或几何术语中的多边形)。我们在优步使用Geofences的基于Geo的配置。这对于向用户展示哪些产品可在给定位置提供,定义具有特定要求的区域,如机场,并在很多人在同一时间要求骑行的社区中实施动态定价。

科罗拉多州的一个例子。
检索基于地理定位的配置的第一步拉特/ Lon对来自用户的手机是找到该位置落入的地Geofence。此功能用于在多个服务/模块中分散和重复。但正如我们一样远离单片架构到(微)面向服务的架构,我们选择将此功能集中到一个新的微服务中。
预备,准备,开始!
node.js.是我们评估语言时实时市场团队的主要编程语言,从而有更多内部知识和经验。但是,有关以下原因,请达到我们的需求:
- 高吞吐量和低延迟要求。来自优步移动应用程序的每个请求都需要Geofence查找,并且必须快速(第99百分位数<100毫秒)回答高速率(数十万千秒)的查询。
- CPU强化工作量。Geofence查找需要CPU密集型点多边形算法。虽然Node.js适用于我们的其他服务的其他服务,但由于节点的情况,在此用例中,它在此用例中是最佳的解释和动态类型自然。
- 无振动背景装。为确保我们拥有最新的Geofences数据来执行查找,这项服务必须继续从背景中的多个数据源中刷新内存内部地理源数据。因为node.js是单螺纹背景,背景刷新可以延长CPU(例如,用于CPU密集杰森解析工作),导致查询响应时间中的尖峰。这不是出现的问题戈罗琳可以在多个CPU核心上执行并运行与前景查询并行的后台作业。
到Geo指数或不是:这是问题
鉴于指定为LAT / LON对的位置,我们如何发现这一切的哪个地理繁想该位置落入?Brute-Force Way很简单:通过所有地理景点并使用算法进行替代点检查,如射线铸造算法。但这种方法太慢了。那么我们如何有效地缩小搜索空间?
而不是使用地理源索引r树或复杂的S2,我们基于优步商业模式为中心的观察来选择更简单的路线;用于定义它们的业务规则和地理源通常与城市相关联。这使我们能够将地理源组织成一个两级层次结构,第一级是城市地理源(定义城市边界的地理景观),第二级是每个城市内的地质。
对于每个查找,我们首先找到所需的城市,具有所有城市地理外的线性扫描,然后在该城市内找到包含另一个线性扫描的Conity的Geofence。虽然解决方案的运行时复杂性仍然存在上),这种简单的技术减少了N从10,000人到100岁的订单。
建筑学
我们希望此服务无状态,因此每个请求都可以转到任何服务实例并期望相同的结果。这意味着每个服务实例都必须了解整个世界,而不是使用分区。我们生成了一个确定性轮询计划,因此来自不同服务实例的地理源数据保持同步。因此,该服务具有非常简单的架构。后台作业定期轮询各种数据存储的地理源数据。反过来,此数据保存在主内存中以提供查询并序列化到本地文件系统以进行快速启动服务重新启动:

我们的地理位置查找服务架构。
处理Go Memory Model
我们的架构需要并发读/写访问我们内存的GEO索引。特别是,背景轮询作业在从索引中读取前景查询引擎时写入索引。对于来自单线程节点的人来说,去记忆模型可能出现挑战。虽然惯用方式是使用Goroutines同步并发读/写渠道,我们担心负面绩效影响。我们试图使用自己的记忆障碍储点/LoadPointer.来自的原语同步/原子包,但导致了脆弱和坚硬维护的代码。
最终,我们在中间地上定居了一个读写锁同步访问GEO索引。为了最大限度地减少锁定争用,在原子上交换到服务查询的主要索引之前,建立了新的索引段。与此相比,这种锁的使用导致查询延迟略微增加储点/LoadPointer.方法,但我们相信CodeBase的简单性和可维护性的增益非常值得小的性能成本。
我们的经验
回顾一下,我们对我们的决定非常满意去因为它并用新语言写下我们的服务。亮点:
- 高开发商生产力。Go通常只需要几天时间才能学习C ++,Java或Node.js开发人员,并且代码易于维护。(谢谢静态打字,不再猜测和令人不快的惊喜)。
- 吞吐量和延迟的高性能。在我们的主要数据中心单独服务非中国交通时,这项服务处理了170K QPS的高峰负荷,40台机器在2015年纽约NYE上运行35%CPU使用率。响应时间为95百分位数<5毫秒,以及<50毫秒第99百分位数。
- 超级可靠。自成立以来,此服务已有99.99%的正常运行时间。唯一的停机时间是由初学者编程错误和第三方库中的文件描述符泄漏错误引起的。重要的是,我们没有看到Go的运行时存在任何问题。
我们从哪里开始?
虽然历史上看优步大多是Node.js和Python商店,但Go语言正在成为建立许多Uber工程的新服务的首选语言。Uber有很多势头,所以如果你热衷于作为专家或初学者,我们是招聘去开发人员。哦,你会去的地方!
照片学分:“金门涌”由Conor Myhrvold,金门公园,旧金山。
标题说明:Go Gopher.被描述为“一个标志性的吉祥物和Go项目中最独特的特征之一。”
喜欢你在读什么?注册我们的通讯对于Uber Engineering Blti8 竞猜雷竞技appog的更新。雷竞技到底好不好用





