高速换轮:Uber如何用微服务重构工程系统?

几个月前,我们讨论过Uber关于放弃它单一整体的代码库,而支持一种模块化的灵活的微服务结构。自那时候以来,我们已经花费了数千个小时,使用多种语言和多种不同的框架来扩展Uber的微服务(数以百计)生态系统。这种持续的重构是一个巨大的挑战,因此,我们趁机在Uber的微服务中采用了一套新的技术。通过一个技术栈和一套符合SOA迁移的标准,我们已经大大简化了整个服务的开发。

 

开始一个新服务  
 

在一个快速发展工程组织中,我们可能很难跟踪所有正在进行的工作。这种增长需要一个流程来防止不同团队之间的重复工作。在Uber,我们通过要求新服务的作者提交一份请求注解(RFC)来解决这个问题,RFC是一个新服务的高层次提案,概述了新服务的目的,架构,依赖,以及其他实现细节,以便其他Uber工程师进行讨论。RFC的目的有两个:

 

1)征求意见,以便提高开发的服务质量,

2)避免重复工作和挖掘合作机会。

 
 

多个熟悉该领域的工程师会审核服务的设计。一旦反馈被纳入服务提案,就可以开始构建有趣的服务。

 

实现一个新服务  
 

Tincup,我们的货币和汇率服务,这是一个很好的关于在Uber如何实现微服务的例子。Tincup是一个最新货币和汇率数据的接口。它有两个主要的服务:第一个是获取货币对象,第二个是获取给定货币的当前汇率(兑美元)。这两项功能是必须的,因为Uber是全球性的业务,汇率变动频繁,我们支持近60种货币的便捷交易。

 

 

无论你在什么地方,你都可以通过点击侧边栏的图标来请求搭车。Tincup能保证你支付的是你所在国家的货币。

 

通过新技术启动微服务  
 

在构建Tincup时,需要重写所有与货币和汇率相关的逻辑,这就提供了一个好的机会来重新评估很久以前在Uber的设计方案。我们使用了很多新的框架,协议,约定来实现Tincup。

 

首先,我们讨论了货币和汇率相关代码的整体结构。

 

在Uber,近几年我们已经多次修改了许多数据集的持久层(像这一次)。每次的改变都是漫长而繁琐的。我们在这个过程中得到了很多经验教训,如果有可能的话,最好是将持久层与具体的应用逻辑进行分离。这就产生了一种应用开发的模式,我们称之为MVCS,它是对我们常用的MVC模式的扩展。它包含了一个服务层来实现应用的业务逻辑,通过将包含业务逻辑的服务层与应用的其它部分进行隔离,持久层就可以在不需要重构业务逻辑的前提下进行升级和替换(只有那些直接处理存储和读取数据的代码需要改变)。

 

其次,我们认真考虑了货币和汇率的持久层。在Tincup之前,数据存在一个ID递增的关系型数据库——PostgreSQL中。

 

然而,这种数据的存储方式不允许Uber的所有数据中心进行全球化的数据复制,因此,这一模式不符合我们现在全面发展(所有的数据中心同时提供服务)的架构。由于全球的数据中心都需要访问货币和汇率,我们在持久层使用UDR(Uber的全球复制可扩展数据存储)来实现数据交换。

 

微服务中心成长的预期顾虑  
 

在决定改变货币和汇率的设计之后,我们解决了很多工程生态系统中由微服务数量不断增加而自然而然会出现的问题。

 

网络I/O的阻塞是一个严重的问题,可能会导致uWSGI工作线程的饥饿。如果所有的请求服务跟Tincup一样都是同步的,一个服务恶化的风险是可能会引起连锁反应,从而影响所有的调用者。我们决定采用Tornado(一个Python的基于循环事件的异步框架)来防止阻塞。由于我们已经将大量的代码从整体的基础代码库分离出来,我们便通过选择一个异步框架来保持现有应用逻辑保持与原来逻辑相同,这一点对保证风险最小化是非常重要的。Tornado满足我们这个要求,因为它允许我们使用一种非阻塞式的I/O来同步查找代码(此外,为了解决上述的I/O问题,许多服务的提供者使用一种新的Go语言)。

 

曾经单个API的调用现在可能会波及到许多的微服务调用。为了便于在一个大的生态系统中发现其它服务和识别失败的点,Uber微服务在Hyperbahn(一个针对RPC在内部开发的网络多路复用帧协议)上使用开源的TChannel,TChannel为客户端和服务端提供协议,这两者通过Hyperbahn的智能路由进行连接。它解决了微服务世界中的几个核心的问题:

1
服务发现。所有的生产者和消费者通过路由网进行自我注册。消费者通过生产者的名称进行访问,而不需要知道生产者的服务器或端口。

 2
容错。路由网可以追踪故障率和SLA( 服务等级协议)违例。它可以检测到不健康的主机,并随后将其从可用的主机池中进行删除。

 3
速率限制和电路断开。这些特性确保来自客户端的错误请求和响应慢不会引起级联故障。

 
 

由于微服务调用数量的快速增长,有必要为每个调用维护一个定义良好的接口。我们很清楚需要使用IDL(接口定义语言)来进行维护,我们最终决定使用Thrift。Thrift强制服务的提供者发布严格的接口定义,这就简化了整合服务的过程。Thrift拒绝不遵守接口定义的调用,而不是将其泄露到更深层次的代码而引起故障。这种公开声明接口的策略,强调向后兼容的重要性,因为多个版本的Thrift服务接口可能在任意时间中同时使用。服务的作者不能对接口做重大修改,只能对定义好的接口添加一些非重大改变的内容,直到所有消费者都不再使用。

 

让Tincup成为行业佼佼者的准备:产品  
 

最后,在Tincup的实现阶段将要完成时,我们是用一些有用的工具来准备生产环境的Tincup:

 

首先,我们知道Uber的流行每天、每周、每年都是变化的。我们可以在预期的时间内看到巨大的高峰期,如除夕和万圣节,所以我们必须在发布之前确保这些服务能够处理这些增加的负载。按要求,在Uber发布一个新服务时,我们使用我们内建的Hailstorm来进行负载测试,确定Tincup功能点的缺陷和服务的中断点。

 

然后,我们考虑Uber工程的另一个主要目标:更加有效的使用硬件。因为Tincup是一个相对轻量级的服务,它很容易与其他微服务共享机器。服务就是关爱,对吧?当然,事情也不总是如此:我们还是想确保每个服务独立运行,而不影响在同一台机器上的其他服务。为了防止这个问题,我们使用uContainer(Uber的Docker)来部署Tincup,以实现资源的隔离和限制。

 

正如其名称所暗示的,uContainer使用Linux的容器功能和Docker来实现Uber服务的容器化。它将一个服务包装在一个隔离的环境中,以保证即使有其他服务在同一台主机上运行,该服务也能够始终如一的运行。uContainer扩展了Docker的功能,在Docker容器中增加了:

1)更灵活的构建功能

2)更多可视化工具。

 
 

最后,为应对生产环境中不可避免的宕机和网络连接问题所做的准备,我们使用一个称之为uDestroy的内部工具来释放服务控制混乱问题。通过模拟宕机,我们可以认识的系统的恢复能力。由于我们在其发展的过程中定期的、有目的破坏系统,我们可以发现系统的漏洞,不断的提高系统耐用性。

 

完成后的经验教训  
 

通过构建Tincup来扩展 SOA的过程中,我们学到几条经验教训:

 

  1. 用户的的迁移是一个长期的、缓慢的过程,所以尽可能的做到操作简单。提供代码示例。预测迁移完成所需的时间。
  2. 技术栈的学习最好是建立在一个小的服务上。Tincup的应用逻辑非常简单,这样开发者可以集中精力去学习新的技术栈,而不是浪费时间在业务逻辑的迁移上。
  3. 开发的初始阶段投入大量的时间在单元测试和集成测试,最终会收到回报的。在开发环境中执行代码调试会简单很多(压力也更小)。
  4. 尽可能早的、频繁的去做负载测试。没有什么事情比发现你花费了几周或几个月实现的系统无法处理流量峰值更糟的了。

 

Uber的微服务  
 

Uber的SOA迁移为许多服务提供者,甚至是那些行业经验有限的人展示了机会。拥有一个服务是一项很大的责任,但是Uber开放的、知识共享的文化使得选择一套新的技术和拥有一个代码库成为了一种有回报、有价值的体验。

 

来源:解放号杰微刊

译者:刘晓鹏


时间: 2024-09-17 04:34:35

高速换轮:Uber如何用微服务重构工程系统?的相关文章

微服务——程序员的自我修养

微服务在2016年成为仅次于物联网和认知计算的第三热门技术,微服务究竟有何等神通,让ThoughtWorks.Netflix.Amazon.Uber等公司趋之若鹜? 传统应用之殇 版本发布·千年等一回 在过去传统企业应用开发模式下,每当遇到需求要修改时,不得不按照大颗粒系统发布版本,瀑布式的版本计划困住了程序员那优雅的双手. 应用升级·祝你平安 应用无法做到永远在线,大版本升级时,不得不停机中断服务.一个小小的问题就有可能带来整个系统的崩溃. 技术选型·独角戏 技术实现单一,需要想办法用一种技术

微服务的4大设计原则和19个解决方案

作者|郝炎峰 编辑|小智 本文将介绍微服务架构的演进.优缺点和微服务应用的设计原则,然后着重介绍作为一个"微服务应用平台"需要提供哪些能力.解决哪些问题才能更好的支撑企业应用架构. 注:本文转载自公众号 EAWorld,已获授权. 写在前面 微服务架构现在是谈到企业应用架构时必聊的话题,微服务之所以火热也是因为相对之前的应用开发方式有很多优点,如更灵活.更能适应现在需求快速变更的大环境. 微服务平台也是我目前正在参与的,还在研发过程中的平台产品,平台是以 SpringCloud 为基础

微服务的4个设计原则和19个解决方案

微服务架构现在是谈到企业应用架构时必聊的话题,微服务之所以火热也是因为相对之前的应用开发方式有很多优点,如更灵活.更能适应现在需求快速变更的大环境. 本文将介绍微服务架构的演进.优缺点和微服务应用的设计原则,然后着重介绍作为一个"微服务应用平台"需要提供哪些能力.解决哪些问题才能更好的支撑企业应用架构. 微服务平台也是我目前正在参与的,还在研发过程中的平台产品,平台是以SpringCloud为基础,结合了普元多年来对企业应用的理解和产品的设计经验,逐步孵化的一个微服务应用平台. 一.微

微服务架构的理论基础 - 康威定律

概述 关于微服务的介绍,可以参考微服务那点事. 微服务是最近非常火热的新概念,大家都在追,也都觉得很对,但是似乎没有很充足的理论基础说明这是正确的,给人的感觉是 不明觉厉 .前段时间看了Mike Amundsen <远距离条件下的康威定律--分布式世界中实现团队构建>(是Design RESTful API的作者)在InfoQ上的一个分享,觉得很有帮助,结合自己的一些思考,整理了该演讲的内容. 可能出乎很多人意料之外的一个事实是,微服务很多核心理念其实在半个世纪前的一篇文章中就被阐述过了,而且

如何构建微服务架构

本文讲的是如何构建微服务架构[编者的话]"微服务"的概念兴起于四五年前,近几年尤其火热,各大厂都在进行微服务化改造和微服务建设.最近一年来我们也参与了微服务化的改造大军,这里写下一些做微服务系统设计和开发时的切身感受. [3 天烧脑式基于Docker的CI/CD实战训练营 | 北京站]本次培训围绕基于Docker的CI/CD实战展开,具体内容包括:持续集成与持续交付(CI/CD)概览:持续集成系统介绍:客户端与服务端的 CI/CD 实践:开发流程中引入 CI.CD:Gitlab 和 C

什么是微服务架构?

什么是微服务? 微服务(Microservices Architecture)是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成.系统中的各个微服务可被独立部署,各个微服务之间是松耦合的.每个微服务仅关注于完成一件任务并很好地完成该任务.在所有情况下,每个任务代表着一个小的业务能力. 单体架构(Monolithic Architecture ) 企业级的应用一般都会面临各种各样的业务需求,而常见的方式是把大量功能堆积到同一个单体架构中去.比如:常见的ERP.CRM等系统都以单体架构的方式

应对海量并发请求,首席布道师谈微服务的应用架构设计

 何李石七牛云首席布道师   <Go语言程序设计>译者,Go语言/容器虚拟化技术布道师.实践者. 5年以上互联网创业经验和企业级产品研发.运营经验,同时也是互联网产品基础架构解决方案专家.   随着互联网网民数的爆发式增加以及人们对随时随地接入互联网诉求的加强,互联网产品需要面对的并发请求量越来越大,云计算的诞生和普及为海量并发请求的应用提供了弹性的硬件支撑. 本案例分享基于微服务的应用架构设计,内容涉及如何构建一个微服务应用,服务注册与发现,微服务测试和典型的微服务架构设计模式,以及微服务架

再论微服务架构之七宗罪

2014年年底,塔里克·阿贝卓布(TareqAbedrabbo,OpenCredo首席技术官)发表了一篇题为"微服务之七宗罪"的文章,他在此文确定了微服务架构七种常见的反发展模式.2016年一月,来自Voxxed的Danial Bryant发表了该文章的最终版,结合原文以及自己的经验对此文做了进一步的更新. 两人讨论的第一个问题都是构建错误的东西.就像Abedrabbo文章说的那样,可能是由于在定义项目范围和目标时含糊不清所造成的,或者像Bryant说的,试图利用最新的技术,而不是使用

现代企业架构下的微服务

本文讲的是现代企业架构下的微服务[编者的话]微服务架构获得了如此多的关注,大多数的企业IT从业者也正好奇它是如何影响其他的架构模式的:比如企业集成和API管理. 本篇博文的目的是提供一个视角: 在我们引入了微服务架构到企业中以后,现代的企业机构会看起来是什么样子.(如果你对微服务架构还很陌生的话,参阅我的前一篇博文.) 关于微服务如何适用到总体的IT版图的讨论, 我以解读Gartner关于微服务的报告来开始. 微服务架构,本质上是消除了很多的复杂性,包括设计的,开发的,部署的,以及跨服务/系统通