当前位置: 首页 > 科技观察

面向领域的微服务架构

时间:2023-03-19 13:58:15 科技观察

undefined事实证明,这种权衡在很多情况下都是有意义的,但它也是反对过早采用微服务架构的有力论据。动机在Uber,我们也采用了微服务架构,因为我们(2012-2013年左右)主要有两个单体服务,遇到了很多微服务解决的运维问题。可用性风险。单一代码库中的单个回滚可能会导致整个系统崩溃(在本例中,是整个Uber)。部署是有风险和昂贵的。在需要频繁回滚的情况下,执行这些操作既困难又耗时。不平滑的关注点分离。在大型代码库中,很难保持良好的关注点分离。特别是在指数级增长的环境中,权宜之计有时会导致逻辑和组件之间的界限模糊。执行效率低下。这些问题加在一起,使团队难以独立自主地执行任务。随着Uber从10多名工程师发展到100多名工程师,多个团队拥有技术堆栈的碎片,这种单一结构将团队的命运绑在一起,难以独立运营。因此,我们采用了微服务架构。最终,我们的系统变得更加灵活,让团队更加自主。系统可靠性。在微服务架构中,整体系统的可靠性增加。单个服务可以关闭(并回滚)而不影响整个系统。关注点分离。在架构上,微服务架构迫使你问“为什么这个服务存在?”并且更清楚地定义了不同组件的角色。清晰的所有权。代码所有者会变得更加清楚。服务通常由个人、团队或组织级别拥有,从而实现更快的增长。自主执行。独立部署更清晰的所有权允许不同的产品和平台团队自主执行。开发速度。应用程序团队可以独立部署他们的代码,这使他们能够按照自己的项目时间表执行。可以毫不夸张地说,如果没有微服务架构,Uber将无法达到今天的规模和执行质量。然而,随着公司规模的进一步扩大,从100多名工程师增加到1,000多名工程师,我们开始注意到一系列与系统复杂性大幅增加相关的问题。在微服务架构下,人们用单一的整体代码库来换取黑盒。黑匣子的功能随时可能发生变化,极易引发事故。例如,工程师必须通过12个不同团队的大约50个服务来调查问题的根本原因。理解服务之间的依赖关系会变得非常困难,因为服务之间的调用可能会深入很多层。第n个依赖项的延迟峰值可能会导致上游出现一系列问题。如果没有合适的工具,就不可能看到实际发生了什么,从而使调试变得困难。为了构建一个简单的功能,工程师通常需要跨多个服务工作,所有服务都由不同的个人和团队拥有。这需要跨部门和团队协作,花时间参加会议、设计和代码审查。随着团队在彼此的服务中构建代码、修改彼此的数据模型,甚至代表服务所有者执行部署,早期明确的服务所有权界限受到损害。网络单体可能会形成,其中看似独立的服务必须全部部署在一起,以便安全地执行任何更改。这样做的结果是开发进度变慢,服务归属不稳定,迁移难度加大。对于已经采用微服务架构的企业来说,没有回头路可走。变成了“活不下去,活不下去”。Domain-OrientedMicroserviceArchitecture如果我们可以把微服务看成是I/O-bound库,把“微服务架构”看成是大型的分布式应用,那么我们就可以使用众所周知的架构来思考如何组织代码。因此,“面向领域的微服务架构”在很大程度上借鉴了既定的代码组织方式,例如领域驱动设计、清晰的架构、面向服务的架构以及面向对象和面向接口的设计模式。我们认为DOMA仅仅是一种创新,因为它是一种相对新颖的方法,可以在大型应用程序的分布式系统中利用既定的设计原则。与DOMA相关的核心原则和术语如下:相关微服务的集合称为域域的集合称为层。域所属的层决定了允许该域内的微服务承担哪些依赖关系,称为层设计为域提供接口,这些域被视为集合的单个入口点,称为网关确定每个域应该如何不可访问来自其他领域众所周知,一个领域不应该在其代码库或数据模型中硬编码与另一个领域相关的逻辑。由于团队通常需要在另一个团队的域中包含逻辑(例如,自定义验证逻辑或数据模型上的某些元上下文),我们提供了一个扩展架构来支持该域中定义明确的扩展点。通过提供系统架构、域网关和预定义的扩展点,DOMA旨在将微服务架构从复杂的事物转变为易于理解的事物:一组灵活、可重用和分层的结构化组件。这篇文章的其余部分将深入探讨Uber对DOMA的实施、我们所看到的好处,以及对可能希望采用这种方法的公司的实用建议。Uber的度量域Uber域表示一个或多个微服务的集合,这些微服务通过逻辑功能分组绑定在一起。设计域时的一个常见问题是“域应该有多大?”一些域可以包含几十个服务,而一些域可以只包含一个服务。重要的任务是仔细考虑每个集合的逻辑作用。比如我们的地图搜索服务是一个域,我们的票价服务是一个域,我们的匹配平台(匹配骑手和司机)也是一个域。这些也不总是遵循公司的组织结构。UberMaps组织本身分为三个域,在三个不同的网关后面有80个微服务。层设计层设计回答了“哪些服务可以调用其他哪些服务?”的问题。在Uber的微服务架构中,我们可以把层设计看成是“大规模的关注点分离”,或者,我们可以把层设计看成是“大规模的依赖管理”。层设计描述了一种机制,用于考虑Uber的故障影响范围和跨服务依赖的产品特殊性。随着域从底层移动到顶层,它们在发生中断时影响的服务更少,并且代表更具体的产品用例。相比之下,底层功能具有更多的依赖性,因此往往具有更大的影响半径并代表一组更通用的业务功能。下图说明了这个概念。将顶层视为具体的用户体验(例如移动功能),将底层视为一般业务功能(例如账户管理或营销旅行)。层仅依赖于它们下面的层,这为我们提供了一个有用的启发式方法来思考影响范围和区域整合等问题。值得注意的是,特征通常会“向下”移动此图,从特定到更一般。可以想象,一个简单的功能,随着需求的增加,最终会成为越来越多的平台。事实上,这种向下迁移是预料之中的,Uber的许多核心业务平台最初都是作为骑手或司机的功能,随着我们开发更多的业务线,它们也变得更加依赖,变得越来越通用(比如UberEats或UberFreight).在优步内部,我们建立了以下五个层次。基础设施层。提供可供任何工程项目使用的功能。这是优步解决存储或网络等重大工程问题的方法。业务层。提供应用程序可以使用的优步功能,但不特定于特定产品类别或业务线(LOB),例如乘车、餐饮或货运。产品层。提供与特定产品类别或LOB相关但与移动应用程序无关的功能,例如几个面向应用程序的Rides(Rider、Rider“Lite”、m.uber.com)使用的“请求乘车”逻辑,ETC。)。表示层。提供与面向消费者的应用程序(移动/网络)中存在的功能直接相关的功能。边缘层。安全地将Uber服务公开给外界。该层还支持移动应用程序。每一层代表越来越具体的功能分组,并且影响半径越来越小(或者换句话说,更少的组件依赖于该层中的功能)。网关在微服务架构中,相信大家对“API网关”这个名词并不陌生。我们在DOMA中定义的网关其实和大家熟知的“API网关”的概念差不多,只是我们倾向于把网关看做是进入基础服务集合(称为域)****的单一入口。网关的成功取决于API设计的成功与否。网关在迁移、服务发现和整体系统复杂性方面提供了许多好处,因为上游消费者仅在单个服务上运行,并且仅依赖于上游服务,而不是依赖域中可能存在的多个下游服务。如果我们从面向对象的设计角度考虑网关,它们是接口定义,允许我们对底层“实现”(在本例中为底层微服务的集合)做任何我们想做的事。扩展扩展表示扩展域的机制。扩展的基本定义是它提供了一种机制来扩展底层服务的功能,而不改变该服务的实际实现,也不影响其整体可靠性。在优步,我们提供两种不同的扩展模型:逻辑扩展和数据扩展。扩展的概念允许我们将架构扩展到可以独立工作的多个团队。逻辑扩展逻辑扩展为扩展服务提供了底层逻辑机制。对于逻辑扩展,我们使用提供者或插件模式的变体,其接口是在服务基础上定义的。这样,扩展团队就可以在不修改底层平台核心代码的情况下,以接口驱动的方式实现扩展逻辑。例如,驱动程序上线。通常,我们会进行各种检查以确保允许驱动程序上线(安全检查、合规性等)。这些都由一个单独的团队拥有。一种方法是让每个团队在同一个端点编写逻辑,但这会增加复杂性。每项检查都需要自定义且完全不相关的逻辑。undefined其中大约50%已经实施,其中大多数都有一些未来采用的计划。未来迁移在优步,我们计算出微服务的半衰期是1.5年,这意味着每1.5年我们就会失去50%的微服务。如果没有网关,微服务架构很容易因为这种流失而陷入“迁移地狱”。改变微服务需要不断的上游迁移。网关使团队能够避免对底层域服务的依赖,这意味着这些服务可以在不强制上游迁移的情况下进行更改。优步去年最大的两个平台重写都发生在网关之后。这些平台有数百种服务依赖于它们,而这些服务将不得不迁移它们现有的平台。在这些情况下,迁移成本可能会非常高,以致于完全重新构建平台是不可行的。新的业务和产品线事实证明,使用DOMA设计的平台更具可扩展性,也更易于维护。Uber的大多数团队都采用了DOMA,因为支持新业务线的成本太高。一些建议本节为可能希望采用DOMA的公司提供一些实用建议。这里的指导原则是,根据我们的经验,一个成熟的、经过深思熟虑的微服务架构是在正确的时间被推向正确的方向的结果。现实情况是,对整个微服务架构进行真正的“重写”是永远不可能的。因此,我们认为微服务架构的演变更像是“修剪树篱”,以便它们最终适当地成长,而不是自上而下或一次性架构(或重新架构)的努力。这是一个动态的、渐进的过程。初创公司的驱动问题应该是“我们什么时候应该采用微服务架构?”和“这对我们的组织有意义吗?”组织提供了运营优势,但以增加复杂性为代价,它们会使构建功能变得更加困难。在较小的公司中,运营收益可能无法抵消增加的架构复杂性。此外,微服务架构通常需要专门的工程资源来支持,这可能超出早期公司的预算,或者从优先级的角度来看不是最优的。考虑到这一点,暂时推迟完全采用微服务并不是没有道理的。如果一个组织确实选择采用微服务,它应该考虑“微服务作为一个大型分布式应用程序”的类比,以及它想要构建的微服务之间的关注点分离。此外,要意识到第一个微服务可能是最重要的并且持续时间最长,因为它们真正描述了业务的核心。中型一旦公司达到中等规模,拥有多个团队,并且不同功能和平台之间的清晰分离变得模糊,微服务架构就变得更加有用。在这一阶段,可以开始思考微服务之间的层次结构。随着某些服务开始对业务运营变得更加重要并且越来越多的团队依赖于它们,依赖性管理可能会变得更加重要。对平台化的早期投资可能会在未来得到回报。如果可以创建一个完全与产品无关的业务平台,并避免核心平台服务中的任意产品逻辑,则可以避免这里的技术债务。在这一点上,使用扩展来实现这一点可能是有意义的。鉴于微服务的数量可能相当少,将它们混为一谈可能没有意义。不过,这里值得注意的是,在Uber的DOMA实现的上下文中,域可以包含服务,因此以“面向域”的方式思考可能仍然有用。大型工程组织可能有数百名工程师和具有多个依赖项的微服务。这时候DOMA就发挥了它的全部作用。很可能会有不同的微服务集群,这些集群可以很容易地分组到域中,前面有一个网关。遗留服务通常开始需要重构或重写,然后再迁移,这意味着如果网关已经到位,它将很快开始提供易于迁移的价值。清晰的层次结构也将变得越来越重要,一些服务作为特定功能或功能组的“产品”服务运行,而其他服务将越来越多地支持多种产品并被视为“平台”。这个阶段的关键是让任何产品逻辑和平台保持解耦,避免平台团队的运维负担过重和整个系统的不稳定。最后的想法随着优步越来越多的团队采用它,我们仍在积极发展DOMA。DOMA的关键见解是,微服务架构实际上只是一个大型分布式程序,您可以像对待任何软件一样,将相同的原则应用于它的演进。DOMA只是在实践中思考这些原则的一种方式。我们希望其他人发现它有用,我们期待反馈。