介绍
最近,围绕服务导向架构和微服务架构的缺陷已经大量讨论。虽然只有几年前,许多人随心所欲地采用了微业架构,因为它们提供了许多效益,例如独立部署形式,明确所有权,系统稳定性的改善,以及更好地分离担忧,近年来人们已经开始为了摧毁微服务,以实现复杂性大大提高复杂性,有时甚至正在制作琐碎的特征难以建设。
由于优步生长至大约2,200个关键的微服务,我们首先经历了这些权衡。在过去的两年里,优步试图减少微服务复杂性,同时仍然保持微服务架构的好处。使用此博客文章,我们雷竞技到底好不好用希望向微服务架构介绍我们的广义方法,我们将其称为“面向域的微服务架构”(Doma)。
虽然近年来它是受欢迎的,但由于这些缺点而批评了微服务架构,但很少有人倡导过于彻底拒绝微安建筑。业务效益太重要,似乎没有,有限,替代方案。我们关于DOMA的目标是为那些希望在保持与微服务体系结构相关的灵活性的同时降低总体系统复杂性的组织提供一种前进的方式。
这件作品解释了Doma,导致采用这种架构的担忧,为优步,它对平台和产品团队的好处,最后,对想要采用这种架构的团队的一些建议。
什么是微服动物?
微服务是面向服务的架构的延伸。与2000年代的相当大的“服务”相反,微服务是代表一套狭隘的功能的应用程序。这些应用程序托管并在网络上提供,并公开了明确定义的接口。其他应用程序通过制作“远程程序调用“(RPC)。
微服务架构的关键特征是托管,调用和部署的代码的方式。如果我们考虑大型单片应用,它们通常被分成具有明确定义的接口的封装组件。然后,这些接口将被直接调用,而不是通过网络而调用。通过这种方式,我们可以开始将微服务视为具有绩效命中(网络I / O和序列化/序列化)的库,以便调用其任何功能。
当我们以这种方式考虑微服务时,我们可能会质疑为什么我们完全采用微服务架构。答案经常独立部署和缩放.对于大型的、整体的应用程序,组织被迫一次部署或发布所有代码。应用程序的每个新版本都可能涉及许多更改。部署变得危险和耗时。任何人都能搞垮整个体系。
换句话说,组织采用微服务操作以牺牲利益为代价表现.组织还必须承担成本以维护支持微服务所需的基础设施。事实证明,在许多情况下,这种权衡造成了很多意义,但它也是针对微服建筑的早产的强烈论据。
动机
在Uber,我们采用了一个微服务架构,因为我们(2012-2013大约)主要是两个单片服务,并耗资微服务解决的许多操作问题。
- 可用性风险。单片代码库中的单一回归可以将整个系统(在这种情况下,所有优步)下来。
- 风险,昂贵的部署。这些频繁需要回滚的痛苦和耗时。
- 令人难度的分离。很难保持与巨额代码基础的良好分离。在指数增长环境中,权宜之计有时会导致逻辑和组件之间的缺点。
- 执行低效。这些问题组合使团队难以自主或独立执行。
换句话说,由于优步从10多岁的工程师增加了多个球队拥有技术堆栈的工程师,整体建筑将团队的命运捆绑在一起,并使难以独立运作。
结果,我们采用了一个微服务架构。最终,我们的系统变得更多灵活的,这使得团队可以拥有更多自主性。
- 系统可靠性。微服务体系结构提高了系统的整体可靠性。单个服务可以关闭(并回滚),而不需要关闭整个系统。
- 关注点分离。结构上,微服务架构强迫您提出问题“为什么这项服务存在?”更清楚地定义不同组件的角色。
- 明确所有权。拥有代码的更清晰。服务通常在个人,团队或ORG级别拥有,从而实现更快的增长。
- 自主执行。独立的部署+更清晰的所有权线解锁了各种产品和平台团队的自主执行。
- 开发人员速度。团队可以独立部署他们的代码,这使他们能够以自己的速度执行。
说优步能够在没有微服架构的情况下实现我们维护的规模和执行质量并不夸张。
然而,由于公司增长了100多个工程师到1000年代,我们开始注意到一系列与大大增加的系统相关的问题复杂.使用微服务体系结构,一个对黑匣子的单一单片代码库,其功能可以随时更改,并且很容易导致意外行为。
例如,工程师必须通过12个不同的团队完成约50个服务,以调查问题的根本原因。
理解服务之间的依赖关系可能会变得相当困难,因为服务之间的调用可能会深入许多层。第n个依赖项中的延迟峰值可能导致上游问题的级联。如果没有正确的工具,就不可能看到实际发生了什么,这使得调试变得困难。
为了构建一个简单的功能,工程师通常必须跨多种服务工作,所有这些都由不同的个人和团队拥有。这需要与在会议,设计和代码审查中花费的时间进行广泛合作。清晰的服务所有权的早期承诺被妥协为团队在彼此服务中构建代码,修改彼此的数据模型,甚至代表服务所有者执行部署。网络巨石可以形成,其中似乎独立的服务必须一起部署,以安全地执行任何更改。
结果是开发者体验较慢,服务所有者的不稳定,更痛苦的迁移等。已经采用的组织采用了微服务架构的组织没有回头。它成为“不能和他们住在一起,不能没有他们生活.”
面向域的微服务架构
如果我们可以把微服务看作是I/O绑定库,而把“微服务架构”看作是一个大型的分布式应用程序,那么我们就可以使用易于理解的架构来考虑如何组织我们的代码。
因此,“面向域的微服务架构”从既定方式绘制了组织代码的既定方式域驱动设计那干净的架构那面向服务的体系结构和面向对象和接口的设计模式。我们认为Doma是创新的,因为它是利用大型组织大型分布式系统中建立的设计原则的相对新颖的方式。
与Doma相关的核心原则和术语如下:
- 我们在相关的微服务系列围绕单独的微服务定向,而不是定向。我们打电话给这些域名。
- 我们进一步创建了我们调用图层的域的集合。域属于的图层建立了允许该域内的微服务允许的依赖性。我们打电话给这一点层设计。
- 我们为域提供干净的接口,我们将这些域视为进入集合的单个入口点。我们打电话给这些网关。
- 最后,我们建立了这一点每个域名都应该不可知为其他域,也就是说,一个域不应该在其代码库或数据模型中有与另一个硬编码的域相关的逻辑。由于团队经常需要在另一个团队的领域中包含逻辑(例如,自定义验证逻辑或数据模型上的一些元上下文),我们提供了一个扩展架构支持域中的良好定义的扩展点。
换句话说,通过提供系统的架构,域网关和预定义的扩展点,Doma打算将微型体系结构从复杂变换到可易于理解的:结构化的灵活,可重用和分层组件。
这篇文章的其余部分挖掘了优步的实施Doma,我们所看到的好处,以及可能想要采用这种方法的公司的实用建议。
优步的实施
域名
优步域名表示一个或多个微服务的集合,这些微服务与功能的逻辑分组相关联。设计域时的一个常见问题是“域应该有多大?”这里我们不提供任何指导。有些域可以包含数十个服务,有些域只能包含一个服务。重要的任务是仔细思考逻辑每个集合的角色。例如,我们的地图搜索服务构成了一个域,票价服务是一个域,匹配平台(匹配乘客和司机)是一个域。这些也并不总是遵循公司的组织结构。优步地图组织本身被分成三个域,在三个不同的网关后面有80个微服务。
层设计
层设计回答“什么服务可以称之为其他服务?”的问题。在优步微型机器人体系结构中。结果,我们可以将层设计视为“在规模上分离担忧”。或者,我们可以将层设计视为“尺度依赖管理”。
层设计描述了一种思考在优步的服务依赖性的失败爆炸半径和产品特异性的机制。由于域从底层向顶层移动,因此在中断的情况下,它们会影响更少的服务,并且代表更具体的产品用例。相反,底层的功能有更多的家属,结果倾向于具有更大的爆炸半径并代表更一般的业务功能。下图说明了这一概念。
可以将顶部层视为特定的用户体验(例如移动功能),底层作为广义业务功能(例如账户管理或市场旅行)。图层只依赖于它们下面的层,这给了我们一个有用的启发式,以考虑爆炸半径和域集成等问题。
值得注意的是,功能经常从特定于更多一般的情况下“向下”这个图表。人们可以想象一个简单的功能,最终变得越来越多的平台,因为要求发展。In fact, this sort of migration downward is expected, and many of Uber’s core business platforms started as rider or driver specific functionality that became more generalized as we developed more lines of business and they took on more dependencies (such as Uber Eats or Uber Freight).
在优步内,我们建立了以下五层。
- 基础设施层。提供任何工程组织可以使用的功能。它是优步的答案,对大型工程问题,如存储或网络。
- 业务层。提供优步作为组织可以使用的功能,但这不是特定于特定产品类别或商业范围(LOB),如骑行,吃或运费。
- 产品层。提供与特定产品类别或LOB有关的功能,但是对移动应用程序不可知,例如“请求乘坐”逻辑,该逻辑由面向应用程序的多个游乐设施(Rider,Rider“Lite”,M.UBer.com, 等等)。
- 演示。提供与面向消费者的应用程序(移动/web)中存在的特性直接相关的功能。
- 边缘层。安全地向外界公开优步服务。此图层也是移动应用程序意识到。
正如您所看到的,每个后续层都代表了一个日益特定的功能分组,并且具有越来越小的爆炸半径(换句话说,依赖于该层内功能的组件越来越少)。
网口
术语“Gateway API”已经是一个广泛建立MicroService架构中的概念。我们的定义与既定的定义没有大幅度变化,除非我们倾向于独家认为网关单一入口点进入一系列底层服务,我们称之为领域。网关的成功依赖于API设计的成功。
由于上游消费者仅在单一服务上运营,因此网关在众所周期以来提供众多好处未来的迁移,发现性,和整体减少系统复杂性使用上游服务仅采用单个依赖性,而不是在域中可能存在的几个下游服务的依赖关系。如果我们考虑在OO设计的意义上的网关,它们是界面定义,它使我们能够根据底层的“实现”(在这种情况下,以底层微服务的集合)来做任何我们想要的。
延期
扩展代表了一种机制延长域名。扩展的基本定义是它提供了一种在不改变该服务的实际实现的情况下扩展底层服务的功能,而不会影响其整体可靠性。在优步我们提供两个不同的扩展模型:逻辑扩展和数据扩展.扩展的概念使我们能够将我们的架构扩展到能够彼此独立工作的多个团队。
逻辑扩展
逻辑扩展为扩展服务的底层逻辑提供了一种机制。对于逻辑扩展,我们使用A的变体提供者或者插入使用旁边定义的接口的模式。这使其使扩展团队能够以接口驱动的方式实现扩展逻辑,而无需修改底层平台的核心代码。
例如,司机上线。通常,我们制作各种检查,以确保允许驾驶员上网(安全检查,合规等)。这些中的每一个都由个人团队拥有。实现这一点的一种方法是在同一端点中拥有每个团队编写逻辑,但这可以引入复杂性。每个检查都需要自定义,并完全无关,逻辑。
在逻辑扩展的情况下,“上网”端点将定义一个接口,它们期望每个扩展符合预定义请求类型和响应。每个团队都会注册将负责执行此逻辑的扩展。在这种情况下,他们可能只是对司机进行一些上下文并返回BOOL,请说如果司机可以在线上线。上机端点将简单地遍历这些响应,并确定其中的任何一个是假的。
这将从每个扩展中解耦核心代码,并在扩展之间提供隔离,这不知道其他逻辑正在执行什么。它很容易构建更多功能,例如可观察性或功能标记。
数据扩展
数据扩展提供了一种用于将任意数据附加到接口的机制,以避免融合核心平台数据模型。对于数据扩展,我们利用Protobuf任何功能使团队可以将任意数据添加到请求。服务通常将存储此数据或将其传递给逻辑扩展,以便核心平台永远不会负责反序列化(因此“了解”)此任意上下文。Protobuf的任何实施都有一些基础设施开销,以换取更强的打字。对于更简单的实现,可以轻松地使用JSON字符串来表示任意数据。
自定义
在逻辑和数据扩展之外,Uber的许多团队都介绍了他们自己的扩展模式,适合他们的域。例如,与我们的演示架构相关的大部分集成都使用基于DAG的任务执行逻辑。
好处
Uber几乎每个主要领域都受到Doma的某种程度的影响。在去年,我们主要专注于优步的业务层,为我们的各种业务行业提供广义逻辑。
DOMA在Uber还很年轻,我们很高兴在未来分享更多关于我们架构的数据和深入的例子。然而,早期的迹象在简化开发人员体验和整体系统复杂性的降低方面是非常积极的。
产品和平台
Doma是超级产品和平台团队的共识努力的结果。平台支持成本通常会下降一个数量级。产品团队受益于保护轨道和加速发展。
例如,我们的扩展架构的早期平台消费者能够从三天到三天下降到优先顺序并将新功能集成的时间采用延长架构的数小时,用于代码审查,规划和消费者的学习曲线。
减少复杂性
以前的产品团队将不得不称之为众多下游服务来利用域名;他们现在只需要一个。通过减少在船上的接触点的数量,平台能够将船上时间减少25-50%。此外,我们能够将2200个微服务分类为70个域。其中大约50%已实施,其中大部分有一些计划未来的采用。
未来的迁移
在Uber,我们计算出微服务的半衰期为1.5年,这意味着每1.5年就有50%的微服务流失。如果没有网关,微服务体系结构很容易因此而陷入“迁移地狱”。不断变化的微服务经常需要上游迁移。网关使团队能够避免依赖于基础域服务,这意味着这些服务可以在不强制上游迁移的情况下更改。
Uber在去年的两个最大的平台重写在网关后面发生。这些平台有数百种服务,依赖于他们必须迁移现有的消费者。在这些情况下迁移的成本非常高,使得一个完整的平台重写不可行。
新的商业和产品
使用Doma设计的平台已被证明可以更广泛,更易于维护。采用Doma的优步的大多数球队所做的是因为支持新的业务线变得太贵了。
实用建议
本节为可能需要采用DOMA的公司提供一些实用的建议。这里的指导原则是,在我们的经验中,一个成熟和周到的微服务源处源于正确的时间在正确的方向上的安静浅点。现实是一个完整的微闲建筑的真正的“重写”是不可能的。
因此,我们认为发展微服务体系结构更像是“修剪篱笆”,以便最终正确地增长,而不是自顶向下或一次性的体系结构(或重新体系结构)工作。这是一个动态和渐进的过程。
初创公司
驾驶问题应该是“我们应该什么时候采用微服架构?”“它对我们的组织有意义吗?”正如我们在上面所见,虽然微服务对具有大量工程师的组织提供了运营效益,但这条件随着复杂性的增加,可以使功能更加难以建立。
在小型组织中,运营利益可能不会抵消建筑复杂性的增加。此外,微服务架构通常需要专门的工程资源来支持,这些资源可能因早期阶段公司或从优先级的角度来看不可预算。
考虑到这一点,在一段时间内完全抵消微服务并不是不合理的。如果组织确实选择采用微服务,它应该考虑“微服务作为大分布式应用程序”的类比,并且它想要构建的微服务之间的关注分离。此外,认识到,第一个微服务可能是最重要,最长的持久性,因为他们真正描述了业务的核心。
中号
一旦公司成为多个团队的中型,并且在不同的特征和平台之间明确分离令人担忧,微服务架构变得更加明显。
正是在这个阶段,人们可以开始考虑微服务之间的层次结构。依赖管理可能变得更加重要,因为一些服务开始对业务运营更加明显至关重要,而且越来越多的团队依赖于它们。
平台化的早期投资可能会向道路划分股息。如果人们可以在此处避免技术不可行的商业平台,并且避免在核心平台服务中的任意产品逻辑,有可能避免技术债务。在这一点上采用扩展可能有意义,以实现这种目标。
考虑到微服务的数量可能仍然很低,将它们聚集在一起可能没有意义。然而,值得注意的是,在Uber的DOMA实现的上下文中,一个领域可以包含单个服务,所以以“面向领域”的方式思考仍然是有用的。
大
较大的工程组织可能拥有数百名工程师和微服务以及几个依赖性。在这一点上,Doma达到了它的全部有用性。可以很明显的微野跑簇,可以容易地将与它们面前的网关一起分组。遗留服务经常开始重构或重写然后迁移,这意味着如果已经到位,网关很快就会开始提供价值。
清晰的层次结构也将越来越重要,这些服务对于作为“产品”服务的某些服务,特别是特定功能或分组功能,而其他服务将越来越多地支持多个产品并被视为“平台”。这在这个阶段至关重要,以使任意产品逻辑与平台分离,以避免平台团队的繁重运行负担以及系统范围的不稳定。
最后的想法
我们仍然积极发展Doma,因为Uber的越来越多的团队来采用它。Doma的关键洞察力是微服务架构真正只有一个,大型分布式的程序,您可以将相同的原则应用于其应用于任何软件的演变。Doma只是一种在实践中思考这些原则的方法。我们希望其他人发现它很有用,我们期待反馈!
Doma本身是交叉功能努力的结果,这涉及在优步的每个组织中涉及近60名工程师。一些特殊的致谢,对于在过去的2年里大量投入这种努力的人......
亚历克斯·齐尔曼,亚历山大·威廉,Allen Lu, Ankit Srivastava,Anthony Tran,Anupam Dikshit,Anurag Biyani,Daniel Wolf,Davide D'Agostino,Deepti Chedda,Dmitriy Bryndin,Gaurav Tungatkar,Jacob Greenleaf,Jaikumar Ganesh,Jennie Ngyuen,Joe Mccabe,约书亚希望尔,朱莉娅法律,库萨卡普尔,琳达傅,麦丹·桑帕维提,nimish sheth,parth shah,Shawn Burke,Simon Newton,史蒂夫•舍伍德Uday Kiran Medisetty和Waleed Kadous
致谢:
这项工作带来了行业中多个现有的设计模式来解决Uber的问题,同时也提出了新的模式,比如扩展。我们感谢行业为他们所做的工作。我们也要感谢Linkedin的工程师超级块谁对我们谈到了他们的经历。







