几个月前,我们讨论了优步决定放弃它的单片代码基,支持模块化、灵活的微服务体系结构。从那时起,我们投入了成千上万的工程时间来扩展Uber微服务的生态系统(几百个,还在增加),用各种语言编写,使用许多不同的框架。这种持续的重构是一项巨大的工程,所以我们抓住机会采用了一套新的技术来构建Uber的微服务。有了非常适合SOA迁移的技术堆栈和标准,我们简化了Uber的服务开发。
启动新服务
在一个快速成长的工程组织中,很难跟踪所有正在进行的工作。这种增长需要一个过程来防止跨团队的重复工作。在Uber,我们通过要求新服务的作者提交一个评论请求(Request for Comments, RFC)来解决这个问题,RFC是对新服务的高级建议,概述其用途、架构、依赖关系和其他实现细节超级工程讨论。RFC有用两个目的:1)征求提高服务质量的反馈,以防止重复努力或公布合作机会。
熟悉域名的其他几名工程师审查服务的设计。一旦反馈结合到服务提案中,就会开始建立服务的乐趣和游戏。
实现新服务
Tincup,我们的货币和汇率服务是如何实现超级服务的一个很好的例子。Tincup是最新货币和汇率数据的界面。它有两个主要端点:一个以获得货币对象,一秒钟以获得给定货币的当前汇率(每美元)。这些端点是必要的,因为优步是全球业务。汇率经常变化,我们促进了近60种货币的交易。
用新技术引导微服务
在创建Tincup时重写所有与货币和汇率相关的逻辑,这为重新评估优步很久以前做出的一些设计决策提供了一个很好的机会。我们使用了一系列新的框架、协议和约定来实现Tincup。
mvc
首先,我们解决了与货币和汇率相关的代码的整体结构。在Uber,我们修改了许多数据集的持久层(如这一个),近年来已经发生了好几次。每一个更改都是冗长而繁琐的。我们从这个过程中了解到,如果可能的话,最好将持久性层细节与应用程序逻辑分离。这就产生了我们所称的应用程序开发方法mvc,扩展了commonMVC包含应用程序逻辑所在的服务层的方法。通过将服务层中的应用程序逻辑与应用程序的其他部分隔离,持久层可以演化或替换,而无需重构业务逻辑(只有直接处理存储/读取数据的代码需要更改)。
UDR
其次,我们考虑了货币和汇率的持久性层。在Tincup之前,该数据存储在关系中PostgreSQL数据库具有增量整数ID。然而,这种数据存储方法不允许在所有优步数据中心跨全局复制的数据,因此不与我们努力保持一致(同时从所有数据中心提供的)架构。由于需要从所有数据中心访问货币和汇率,因此我们将刷新持久层使用UDR,优步全球复制的可伸缩数据存储。
对微服务增长的关注
在决定了特定于货币和汇率的设计更改之后,我们处理了工程生态系统中微服务数量增加时自然出现的新问题。
龙卷风
网络I/O阻塞是可能导致的严重问题uWSGI工人的饥饿。如果对服务(如Tincup)的所有请求都是同步的,那么一个服务的降级可能会导致连锁反应并影响所有调用者。我们决定采用龙卷风,一个基于事件循环的Python异步框架,以防止阻塞。由于我们从(瓶),对于我们来说,通过选择一个异步框架来最小化风险是很重要的,这个框架允许大部分现有的应用程序逻辑保持不变。Tornado满足了我们的要求,因为它允许同步外观的代码,但不阻塞I/O。(另外,为了解决上述I/O问题,许多服务所有者正在尝试一种新的语言。)
TChannel.
一旦单个API呼叫可能会扇动到微服务的大量电话。为了方便发现其他服务和识别大型生态系统中的失败点,Uber MicroServices使用开源TChannel.在Hyperbahn,一个为RPC开发的网络多路复用和帧协议。TChannel为客户端和服务器提供了一种协议,通过Hyperbahn的智能路由网格将两者连接起来。它解决了微服务世界中出现的几个核心问题:
- 服务发现。所有生产商和消费者都将自己注册到路由网格。消费者按名称访问生产者,而不是需要了解主机或端口。
- 容错。路由网格跟踪失败率和SLA违规等度量标准。它可以检测不健康的主机,然后将它们从可用主机的池中删除。
- 限率和断路。这些功能确保了客户端不会导致客户的不良请求和慢响应级联故障。
节俭
由于服务调用的数量增长很快,因此有必要为每个调用维护一个定义良好的接口。我们知道我们想用anIDL来管理这个接口,我们最终决定节俭。Thrift强制服务所有者发布严格的接口定义,从而简化了与服务集成的过程。不遵守接口的调用将在Thrift级别上被拒绝,而不是泄漏到服务中并在代码的更深处失败。这种公开声明接口的策略强调了向后兼容性的重要性,因为一个服务的Thrift接口的多个版本可以在任何给定时间使用。服务作者必须不做破坏性的更改,而只能在所有消费者准备好弃用之前,对接口定义进行非破坏性的添加。
为大联盟准备TinCup:生产
最后,当Tincup的实现阶段接近完成时,我们使用了一些有用的工具来为生产环境准备Tincup:
下得很大的冰雹
首先,我们承认优步的交通与一天中的时间,一天和一年中的一天。我们在预期的时代看到巨大的峰值,如新年的夏娃和万圣节,所以我们必须确保在我们发布它们之前,服务可以处理这种增加的负担。根据优步在推出新服务时,我们使用我们的内部内置下得很大的冰雹为负载测试Tincup的端点并确定缺点和断裂点。
uContainer.
接下来,我们考虑了另一个主要目标超级工程:更有效地使用硬件。由于Tincup是一种相对轻量级的服务,它可以轻松地与其他微服务共享机器。分享是关怀,对吗?嗯,并不总是 - 我们仍然希望确保每个服务独立运行,并且不会影响同一台计算机上运行的其他服务。为了防止这个问题,我们使用的是使用uContainer.(码头工人在Uber)用于资源隔离和限制。由于其名称暗示,UContainer利用Linux容器功能和Docker到Containize Uber服务。它将服务送入孤立的环境,以保证服务将一致地运行,无论同一主机上的其他运行进程如何。UContainer通过添加1)个功能来扩展Docker的功能,以获得更灵活的构建和2)工具,以便在Docker容器中更可见。
uDestroy
最后,为了为生产中不可避免地出现的中断和网络连接问题做准备,我们使用了一个称为uDestroy在我们的服务中释放有控制的混乱。通过在我们自己的条件下模拟破坏,我们可以看到我们系统的弹性。由于我们在系统发展的过程中定期、有目的地破坏系统,我们可以识别漏洞,并不断努力提高系统的耐久性。
实施后学习
我们学到了很多扩大SOA通过建设Tincup:
- 迁移消费者是一个漫长的,缓慢的过程,所以使它尽可能简单。提供代码示例。预算时间通过此迁移来散步。
- 在小型服务上学习技术堆栈是最好的。Tincup的应用程序逻辑非常简单,这使得开发人员可以专注于学习新的技术堆栈,而不是业务逻辑的详细迁移。
- 把最初的时间花在开发广泛的单元和集成测试上,会给以后的发展带来好处。如果在开发环境中调试代码问题就容易得多(压力也更小!)
- 尽可能提前和经常负载测试。没有什么比找出你的系统在花费几周或几个月的实施后无法处理高峰流量的了解。
Microservices在超级
Uber的SOA迁移为许多人提供了拥有服务的机会,即使是那些行业经验有限的人。拥有一项服务是一项重大的责任,但优步开放的、知识共享的文化使掌握一套新技术和拥有一个代码库成为一种有益的和有价值的经验。
艾米丽·莱因霍尔德是软件工程师优步工程的乘客平台钱的团队谁领导了Tincup的开发。
就像你读的?注册我们的通讯获取优步工程博客的更新信息。ti8 竞猜雷竞技app雷竞技到底好不好用





