Introduction 介绍
Recently there has been substantial discussion around the downsides of service oriented architectures and microservice architectures in particular.
最近,围绕面向服务的架构,特别是微服务架构的缺点进行了大量讨论。
While only a few years ago, many people readily adopted microservice architectures due to the numerous benefits they provide such as flexibility in the form of independent deployments, clear ownership, improvements in system stability, and better separation of concerns, in recent years people have begun to decry microservices for their tendency to greatly increase complexity, sometimes making even
虽然就在几年前,许多人很容易采用微服务架构,因为它们提供了众多好处,例如独立部署形式的灵活性、清晰的所有权、系统稳定性的改进以及更好的关注点分离,但近年来,人们已经开始开始采用微服务架构。谴责微服务大大增加复杂性的趋势,有时甚至使trivial features difficult to build.
琐碎的功能很难构建。
As Uber has grown to around 2,200 critical microservices, we experienced these tradeoffs first hand. Over the last two years, Uber has attempted to reduce microservice complexity while still maintaining the benefits of a microservice architecture.
随着 Uber 发展到大约 2,200 个关键微服务,我们亲身经历了这些权衡。在过去的两年里,Uber 一直在尝试降低微服务的复杂性,同时仍然保持微服务架构的优势。
With this blog post we hope to introduce our generalized approach to microservice architectures, which we refer to as “Domain-Oriented Microservice Architecture” (DOMA).
通过这篇博文,我们希望介绍微服务架构的通用方法,我们将其称为“面向领域的微服务架构”(DOMA)。
While it’s been popular in recent years to criticize microservice architectures because of these downsides, few people have advocated an outright rejection of microservice architectures.
尽管近年来由于这些缺点而批评微服务架构很流行,但很少有人主张彻底拒绝微服务架构。
The operational benefits are too important, and it seems that there are no, or limited, alternatives.
运营效益太重要了,而且似乎没有或有限的替代方案。Our goal with DOMA is to provide a way forward for organizations that want to reduce overall system complexity while maintaining the flexibility associated with microservice architectures.
DOMA 的目标是为希望降低整体系统复杂性同时保持与微服务架构相关的灵活性的组织提供一条前进的道路。
This piece explains DOMA, the concerns that led to the adoption of this architecture for Uber, its benefits for platform and product teams, and, finally, some advice for teams who want to adopt this architecture.
本文解释了 DOMA、导致 Uber 采用此架构的担忧、它对平台和产品团队的好处,以及最后为想要采用此架构的团队的一些建议。
What is a microservice? 什么是微服务?
Microservices are an extension of service oriented architectures. As opposed to the fairly large “services” of the 2000s, microservices are applications that represent a set of narrowly scoped functionality.
微服务是面向服务的架构的扩展。与 2000 年代相当大的“服务”相反,微服务是代表一组范围狭窄的功能的应用程序。
These applications are hosted and available over the network and expose a well-defined interface. Other applications call this interface by making a “
这些应用程序通过网络托管和可用,并公开定义良好的接口。其他应用程序通过创建“remote procedure call” (RPC).
远程过程调用(RPC)。
The key characteristic of microservice architecture is the way in which code is hosted, called, and deployed. If we think about large, monolithic applications, they are generally split into encapsulated components with well-defined interfaces.
微服务架构的关键特征是代码的托管、调用和部署方式。如果我们考虑大型的整体应用程序,它们通常被分成具有明确定义的接口的封装组件。
These interfaces would then be called directly in-process as opposed to over the network. In this way, we can start to think of a microservice as a library with a performance hit (network I/O and serialization / deserialization) in order to call any of its functions.
然后,这些接口将在进程内直接调用,而不是通过网络调用。通过这种方式,我们可以开始将微服务视为一个具有性能影响(网络 I/O 和序列化/反序列化)的库,以便调用其任何功能。
When we think about microservices this way, we might question why we would adopt a microservice architecture at all. The answer is often independent deployments and scaling. With a large, monolithic application, an organization is forced to deploy or release all of their code at once. Each new version of an application can involve numerous changes. Deployments become risky and time consuming. Anyone can bring the whole system down.
当我们以这种方式思考微服务时,我们可能会质疑为什么要采用微服务架构。答案通常是独立部署和扩展。对于大型整体应用程序,组织被迫立即部署或发布所有代码。应用程序的每个新版本都可能涉及大量更改。部署变得充满风险且耗时。任何人都可以搞垮整个系统。
In other words, organizations adopt microservices for an operational benefit at the expense of performance. Organizations also must take on the cost to maintain the infrastructure necessary to support microservices. In many situations, it turns out, this trade-off makes a lot of sense, but it is also a strong argument against a premature adoption of a microservice architecture.
换句话说,组织采用微服务是为了以牺牲性能为代价来获得运营效益。组织还必须承担维护支持微服务所需的基础设施的成本。事实证明,在许多情况下,这种权衡很有意义,但它也是反对过早采用微服务架构的有力论据。
Motivations 动机
At Uber, we adopted a microservice architecture because we had (circa 2012-2013) primarily two monolithic services and ran into many of the operational issues that microservices solve.
在 Uber,我们采用了微服务架构,因为我们(大约 2012-2013 年)主要有两个整体服务,并遇到了微服务解决的许多运营问题。
- Availability Risks. A single regression within a monolithic code base can bring the whole system (in this case, all of Uber) down.
可用性风险。单一代码库中的单一回归可能会导致整个系统(在本例中是整个 Uber)瘫痪。 - Risky, expensive deployments. These were painful and time consuming to perform with the frequent need for rollbacks.
部署风险大、成本高。由于频繁需要回滚,执行这些操作既痛苦又耗时。 - Poor separation of concerns. It was difficult to maintain good separations of concerns with a huge code base. In an exponential growth environment, expediency sometimes led to poor boundaries between logic and components.
关注点分离不佳。在庞大的代码库中很难保持良好的关注点分离。在指数增长的环境中,权宜之计有时会导致逻辑和组件之间的界限不清。 - Inefficient execution. These issues combined made it difficult for teams to execute autonomously or independently.
执行效率低下。这些问题加在一起使得团队很难自主或独立执行。
In other words, as Uber grew from 10s to 100s of engineers with multiple teams owning pieces of the tech stack, the monolithic architecture tied the fate of teams together and made it difficult to operate independently.
换句话说,随着 Uber 从 10 多位工程师发展到 100 多位工程师,多个团队拥有部分技术堆栈,单一架构将团队的命运绑在一起,很难独立运营。
As a result, we adopted a microservice architecture. Ultimately our systems became more flexible, which allowed teams to be more autonomous.
因此,我们采用了微服务架构。最终我们的系统变得更加灵活,这使得团队更加自主。
- System reliability. Overall system reliability goes up in a microservice architecture. A single service can go down (and be rolled back) without taking down the whole system.
系统可靠性。微服务架构中的整体系统可靠性得到提高。单个服务可以关闭(并回滚),而无需关闭整个系统。 - Separation of concerns. Architecturally, microservice architectures force you to ask the question “why does this service exist?” more clearly defining the roles of different components.
关注点分离。从架构上来说,微服务架构迫使你问“为什么这个服务存在?”更清晰地定义不同组件的角色。 - Clear Ownership. It becomes much clearer who owned what code. Services are typically owned at the individual, team, or org level enabling faster growth.
所有权清晰。谁拥有什么代码就变得更加清晰。服务通常由个人、团队或组织级别拥有,从而实现更快的增长。 - Autonomous execution. Independent deployments + clearer lines of ownership unlock autonomous execution by various product and platform teams.
自主执行。独立部署+更清晰的所有权关系解锁了各个产品和平台团队的自主执行。 - Developer Velocity. Teams can deploy their code independently, which enables them to execute at their own pace.
开发人员速度。团队可以独立部署他们的代码,这使他们能够按照自己的节奏执行。
It’s not an exaggeration to say that Uber would not have been able to accomplish the scale and quality of execution that we maintain today without a microservice architecture.
可以毫不夸张地说,如果没有微服务架构,Uber 就无法实现我们今天所维持的规模和执行质量。
However, as the company grew even larger, 100s of engineers to 1000s, we began to notice a set of issues associated with greatly increased system complexity. With a microservice architecture one trades a single monolithic code base for black boxes whose functionality can change at any time and easily cause unexpected behavior.
然而,随着公司规模不断扩大,工程师数量从数百名增加到数千名,我们开始注意到一系列与系统复杂性大幅增加相关的问题。通过微服务架构,人们可以将单一的整体代码库换成黑匣子,黑匣子的功能可以随时更改,并且很容易导致意外行为。
For instance, engineers had to work through around 50 services across 12 different teams in order to investigate the root cause of the problem.
例如,工程师必须处理 12 个不同团队的大约 50 项服务,才能调查问题的根本原因。
Understanding dependencies between services can become quite difficult, as calls between services can go many layers deep. A latency spike in the nth dependency can cause a cascade of issues upstream.
理解服务之间的依赖关系可能会变得相当困难,因为服务之间的调用可能会深入很多层。第 n 个依赖项中的延迟峰值可能会导致上游出现一系列问题。
Visibility into what’s actually happening is impossible without the right tools, making debugging difficult.
如果没有正确的工具,就不可能了解实际发生的情况,从而使调试变得困难。
In order to build a simple feature an engineer often has to work across multiple services, all of which are owned by different individuals and teams. This requires extensive collaboration with time spent on meetings, design, and code review.
为了构建一个简单的功能,工程师通常必须跨多个服务工作,所有这些服务都由不同的个人和团队拥有。这需要在会议、设计和代码审查上花费时间进行广泛的协作。
The earlier promise of clear lines of service ownership is compromised as teams build code within each other’s services, modify each other’s data models, and even perform deployments on behalf of service owners.
当团队在彼此的服务中构建代码、修改彼此的数据模型、甚至代表服务所有者执行部署时,早期明确的服务所有权界限的承诺就会受到损害。
Networked monoliths can form, where services that appear to be independent all have to be deployed together to safely perform any change.
网络化的整体架构可能会形成,其中看似独立的所有服务都必须部署在一起才能安全地执行任何更改。
The result is a slower developer experience, instability for service owners, more painful migrations, etc. For organizations that have already adopted a microservice architecture there is no turning back. It becomes a case of “can’t live with them, can’t live without them.”
其结果是开发人员体验变慢、服务所有者不稳定、迁移更加痛苦等等。对于已经采用微服务架构的组织来说,这是没有回头路的。这就变成了“不能和他们一起生活,没有他们就不能生活”的情况。
Domain-Oriented Microservice Architecture
面向领域的微服务架构
If we can think of microservices as I/O bound libraries and a “microservice architecture” as a large, distributed application then we can use well understood architectures to think about how to organize our code.
如果我们可以将微服务视为 I/O 绑定库,并将“微服务架构”视为大型分布式应用程序,那么我们就可以使用易于理解的架构来思考如何组织我们的代码。
“Domain-Oriented Microservice Architecture” thus draws heavily from established ways to organize code such as Domain-driven Design, Clean Architecture, Service-Oriented Architecture, and object- and interface-oriented design patterns. We think of DOMA as innovative only insofar as it is a relatively novel way to leverage established design principles in large distributed systems in large organizations.
因此,“面向领域的微服务架构”大量借鉴了组织代码的既定方法,例如领域驱动设计、简洁架构、面向服务的架构以及面向对象和接口的设计模式。我们认为 DOMA 具有创新性,因为它是一种相对新颖的方式,可以在大型组织的大型分布式系统中利用既定的设计原则。
The core principles and terminology associated with DOMA are as follows:
DOMA 相关的核心原则和术语如下:
- Instead of orienting around single microservices, we oriented around collections of related microservices. We call these domains.
我们不是面向单个微服务,而是面向相关微服务的集合。我们称这些域为域。 - We further create collections of domains which we call layers. The layer that the domain belongs to establishes what dependencies the microservices within that domain are allowed to take on. We call this layer design.
我们进一步创建域的集合,我们称之为层。域所属的层确定了该域内的微服务允许采取哪些依赖关系。我们称之为层设计。 - We provide clean interfaces for domains that we treat as a single point of entry into the collection. We call these gateways.
我们为域提供干净的接口,我们将其视为集合的单个入口点。我们称这些为网关。 - Finally, we establish that each domain should be agnostic to other domains, which is to say, a domain shouldn’t have logic related to another domain hard coded inside of its code base or data models.
最后,我们确定每个域都应该与其他域无关,也就是说,一个域不应该在其代码库或数据模型内硬编码与另一个域相关的逻辑。
Since frequently teams do need to include logic in another team’s domain (for example, custom validation logic or some meta context on a data model), we provide an
由于团队经常需要在另一个团队的域中包含逻辑(例如,自定义验证逻辑或数据模型上的某些元上下文),因此我们提供了一个extension architecture to support well defined extension points within the domain.
扩展架构支持域内定义明确的扩展点。
In other words, by providing a systematic architecture, domain gateways, and predefined extension points, DOMA intends to transform microservice architectures from something complex to something comprehensible: a structured set of flexible, reusable, and layered components.
换句话说,通过提供系统架构、域网关和预定义的扩展点,DOMA 旨在将微服务架构从复杂的东西转变为易于理解的东西:一组灵活的、可重用的、分层的组件的结构化集合。
The rest of this post digs into Uber’s implementation of DOMA, the benefits we’ve seen, and practical advice for companies which might want to adopt this approach.
本文的其余部分深入探讨了 Uber 对 DOMA 的实施、我们所看到的好处,以及为可能想要采用这种方法的公司提供的实用建议。
Uber’s Implementation Uber 的实施
Domains 域名
Uber domains represent a collection of one or more microservices tied to a logical grouping of functionality. A common question in designing a domain is “how big should a domain be?” We give no guidance here.
Uber 域代表与功能逻辑分组相关的一个或多个微服务的集合。设计域时的一个常见问题是“域应该有多大?”我们在这里不提供任何指导。
Some domains can include tens of services, some domains only a single service. The important task is to think carefully about the
有些域可以包含数十个服务,有些域仅包含一个服务。重要的任务是认真思考logical role of each collection. For instance, our map search services constitute a domain, fare services are a domain, matching platform (matching riders and drivers) are a domain. These also don’t always follow company org structure.
每个集合的逻辑角色。比如我们的地图搜索服务是一个域,票价服务是一个域,匹配平台(匹配乘客和司机)是一个域。这些也不总是遵循公司的组织结构。
The Uber Maps org itself is split into three domains, with 80 microservices behind 3 different gateways.
Uber Maps 组织本身分为三个域,3 个不同的网关背后有 80 个微服务。
Layer Design 图层设计
Layer design answers the question of “what service can call what other service?” within Uber’s microservice architecture.
分层设计回答了“什么服务可以调用其他什么服务?”的问题。在 Uber 的微服务架构中。
As a result, we can think of layer design as “separation of concerns at scale.” Alternatively, we can think of layer design as “dependency management at scale.”
因此,我们可以将层设计视为“大规模关注点分离”。或者,我们可以将层设计视为“大规模的依赖管理”。
Layer design describes a mechanism for thinking about failure blast radius and product specificity across service dependencies at Uber. As domains move from the bottom layer to the top layer, they impact fewer services in the case of an outage and represent more specific product use cases. Conversely, functionality at the bottom layers have more dependents and as a result tend to have a larger blast radius and represent a more general set of business functionality. The figure below illustrates this concept.
层设计描述了一种考虑 Uber 跨服务依赖关系的故障爆炸半径和产品特异性的机制。随着域从底层移动到顶层,它们在中断的情况下影响的服务更少,并且代表更具体的产品用例。相反,底层的功能具有更多的依赖性,因此往往具有更大的影响半径并代表更通用的业务功能集。下图说明了这个概念。
One can think of the top layers as specific user experiences (such as mobile features), and the bottom layers as generalized business functionality (such as account management or marketplace trips).
人们可以将顶层视为特定的用户体验(例如移动功能),将底层视为通用的业务功能(例如帐户管理或市场旅行)。
Layers only depend on the layers under them, which gives us a useful heuristic to think about questions like blast radius and domain integration.
层仅依赖于它们下面的层,这为我们思考爆炸半径和域集成等问题提供了有用的启发。
It’s worth noting that functionality often moves “down” this chart from specific to more general. One can imagine a simple feature that eventually becomes more and more of a platform as requirements evolve.
值得注意的是,功能通常会从特定的图表“向下”移动到更通用的图表。人们可以想象一个简单的功能,随着需求的发展,它最终会变得越来越像一个平台。
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).
事实上,这种向下迁移是预料之中的,Uber 的许多核心业务平台最初都是作为乘客或司机的特定功能,随着我们开发更多的业务线并且它们承担了更多的依赖关系(例如 Uber Eats 或 Uber Freight),这些功能变得更加通用。 )。
Within Uber, we established the following five layers.
在 Uber 内部,我们建立了以下五个层次。
- Infrastructure layer. Provides functionality that any engineering organization could use. It’s Uber’s answer to the big engineering questions, such as storage or networking.
基础设施层。提供任何工程组织都可以使用的功能。这是 Uber 对存储或网络等重大工程问题的回答。 - Business layer. Provides functionality that Uber as an organization could use, but that is not specific to a particular product category or line of business (LOB) such as Rides, Eats, or Freight.
业务层。提供 Uber 作为组织可以使用的功能,但并非特定于特定产品类别或业务线 (LOB),例如乘车、餐饮或货运。 - Product layer. Provides functionality that relates to a particular product category or LOB, but is agnostic to the mobile application, such as the “request a ride” logic which is leveraged by multiple Rides facing applications (Rider, Rider “Lite”, m.uber.com, etc).
产品层。提供与特定产品类别或 LOB 相关的功能,但与移动应用程序无关,例如由多个面向 Rides 的应用程序(Rider、Rider“Lite”、m.uber.com)利用的“请求乘车”逻辑, ETC)。 - Presentation. Provide functionality that directly relates to features that exist within a consumer-facing application (mobile/web).
推介会。提供与面向消费者的应用程序(移动/网络)中存在的功能直接相关的功能。 - Edge Layer. Safely exposes Uber services to the outside world. This layer is also mobile application aware.
边缘层。向外界安全地公开 Uber 服务。该层也是移动应用程序感知的。
As you can see, each subsequent layer represents an increasingly specific grouping of functionality, and has a smaller and smaller blast radius (or, in other words, less components depend on the functionality within that layer).
正如您所看到的,每个后续层代表了越来越具体的功能分组,并且具有越来越小的爆炸半径(或者,换句话说,依赖于该层内的功能的组件越来越少)。
Gateways 网关
The term “Gateway API” is already a broadly established concept within microservice architectures. Our definition does not vary greatly from the established definition, except that we tend to think of gateways exclusively as a single entry-point into a collection of underlying services, which we call a domain. The success of a gateway relies on the success of the API design.
术语“网关 API”已经是微服务架构中广泛确立的概念。我们的定义与既定的定义没有太大差异,只是我们倾向于将网关完全视为底层服务集合(我们称之为域)的单个入口点。网关的成功取决于API设计的成功。
Since upstream consumers only operate on a single service, gateways provide numerous benefits in terms of future migrations, discoverability, and overall reduction in system complexity with upstream services only taking a single dependency as opposed to dependencies on several downstream services that might exist within a domain.
由于上游消费者仅对单个服务进行操作,因此网关在未来迁移、可发现性和整体降低系统复杂性方面提供了许多好处,上游服务仅采用单个依赖项,而不是依赖于域中可能存在的多个下游服务。
If we think about gateways in the sense of OO design, they are interface definitions, which enable us to do whatever we want in terms of the underlying “implementation” (in this case the collection of underlying microservices).
如果我们从面向对象设计的角度考虑网关,它们就是接口定义,这使我们能够在底层“实现”(在本例中是底层微服务的集合)方面做任何我们想做的事情。
Extensions 扩展
Extensions represent a mechanism to extend domains. The basic definition of an extension is that it provides a mechanism for extending the functionality of an underlying service without changing the actual implementation of that service and without impacting its overall reliability.
扩展代表了一种扩展域的机制。扩展的基本定义是,它提供了一种扩展底层服务功能的机制,而不改变该服务的实际实现,也不影响其整体可靠性。
At Uber we provide two different extension models:
在 Uber,我们提供两种不同的扩展模型:logic extensions and data extensions. The concept of extensions has allowed us to scale our architecture to multiple teams being able to work independently of each other.
逻辑扩展和数据扩展。扩展的概念使我们能够将架构扩展到能够彼此独立工作的多个团队。
Logic Extensions 逻辑扩展
Logic extensions provide a mechanism for extending the underlying logic of a service. For logic extensions we use a variation of a provider or plugin pattern with an interface defined on a service-by-service basis. This makes it so that extending teams can implement extension logic in an interface-driven way without modifying the core code of the underlying platform.
逻辑扩展提供了一种扩展服务底层逻辑的机制。对于逻辑扩展,我们使用提供者或插件模式的变体,并具有基于服务定义的接口。这使得扩展团队可以通过接口驱动的方式实现扩展逻辑,而无需修改底层平台的核心代码。
For example, a driver goes online. Typically, we make various checks to ensure that a driver is allowed to go online (safety checks, compliance, etc.). Each of these is owned by an individual team.
例如,司机上网。通常,我们会进行各种检查以确保驾驶员可以上网(安全检查、合规性等)。其中每一个都由一个单独的团队拥有。
One way to implement this would be to have each team write logic in the same endpoint, but this can introduce complexity. Each check would require custom, and entirely unrelated, logic.
实现此目的的一种方法是让每个团队在同一端点中编写逻辑,但这可能会带来复杂性。每项检查都需要自定义且完全不相关的逻辑。
In the case of logic extensions, the “go online” endpoint would define an interface that they expect each extension to conform to with a predefined request type and a response. Each team would register an extension that would be responsible for the execution of this logic.
在逻辑扩展的情况下,“上线”端点将定义一个接口,他们希望每个扩展都符合预定义的请求类型和响应。每个团队将注册一个扩展来负责执行该逻辑。
In this case, they might simply take some context about the driver and return a bool, saying if the driver can go online or not. The go online endpoint would simply iterate through these responses, and determine if any of them are false.
在这种情况下,他们可能只是获取有关驱动程序的一些上下文并返回一个布尔值,说明驱动程序是否可以上网。上线端点将简单地迭代这些响应,并确定其中是否有错误。
This decouples the core code from each extension, and provides isolation between extensions, which don’t know what other logic is executing. It’s easy to build up more functionality around this, such as observability or feature flagging.
这将核心代码与每个扩展解耦,并在扩展之间提供隔离,这些扩展不知道正在执行什么其他逻辑。围绕此构建更多功能很容易,例如可观察性或功能标记。
Data Extensions 数据扩展
Data extensions provide a mechanism for attaching arbitrary data to an interface to avoid bloat in core platform data models. For data extensions, we leverage Protobuf’s Any functionality so that teams can add arbitrary data to requests. Services will often store this data or pass it to a logic extension so that the core platform is never responsible for deserializing (and thus “knowing about”) this arbitrary context.
数据扩展提供了一种将任意数据附加到接口的机制,以避免核心平台数据模型膨胀。对于数据扩展,我们利用 Protobuf 的 Any 功能,以便团队可以向请求添加任意数据。服务通常会存储这些数据或将其传递给逻辑扩展,以便核心平台永远不会负责反序列化(从而“了解”)这个任意上下文。
Protobuf’s Any implementation comes with some infrastructure overhead in exchange for stronger typing. For a simpler implementation, one could just as easily use a JSON string to represent arbitrary data.
Protobuf 的 Any 实现都会带来一些基础设施开销,以换取更强的类型。对于更简单的实现,可以轻松地使用 JSON 字符串来表示任意数据。
Custom 风俗
Outside of logic and data extensions, many teams at Uber have introduced their own extension patterns that are appropriate for their domain. For example, much of the integrations tied to our presentation architecture uses DAG based task execution logic.
除了逻辑和数据扩展之外,Uber 的许多团队还引入了自己适合其领域的扩展模式。例如,与我们的表示架构相关的许多集成都使用基于 DAG 的任务执行逻辑。
Benefits 好处
Almost every major domain at Uber has been influenced on some level by DOMA. Over the last year, we have focused primarily on Uber’s business layer which provides generalized logic for each of our various lines of business.
Uber 的几乎每个主要领域都在某种程度上受到了 DOMA 的影响。去年,我们主要关注 Uber 的业务层,该层为我们的各个业务线提供通用逻辑。
DOMA is still young at Uber, and we are excited to share more data and in-depth examples of our architecture in the future. However, early signs have been extremely positive in terms of a simplified developer experience and a reduction in overall system complexity.
DOMA 在 Uber 中还很年轻,我们很高兴将来能分享更多数据和我们架构的深入示例。然而,在简化开发人员体验和降低整体系统复杂性方面,早期迹象非常积极。
Products & Platforms 产品与平台
DOMA was the result of a consensus effort across product and platform teams at Uber. Platform support costs often dropped an order of magnitude. Product teams benefited from guard rails and accelerated development.
DOMA 是 Uber 产品和平台团队一致努力的结果。平台支持成本通常会下降一个数量级。产品团队受益于护栏和加速开发。
For example, an early platform consumer of our extensions architecture was able to drop the time to prioritize and integrate a new feature from three days to three hours by adopting an extension architecture with reduced time for code review, planning, and learning curve for consumers.
例如,我们的扩展架构的早期平台消费者通过采用可减少消费者代码审查、规划和学习曲线时间的扩展架构,能够将确定新功能优先级和集成新功能的时间从三天缩短到三个小时。
Reduced Complexity 降低复杂性
Previously product teams would have to call numerous downstream services to leverage a domain; they now have to call just one. By reducing the number of touchpoints to onboard a new feature, platforms were able to reduce onboarding time by 25-50%.
以前,产品团队必须调用大量下游服务才能利用某个域;他们现在只需拨打一个电话即可。通过减少新功能上线的接触点数量,平台能够将上线时间缩短 25-50%。
Furthermore, we were able to classify 2200 microservices into 70 domains. Roughly 50% of which have been implemented, and most of which have some plan for future adoption.
此外,我们能够将 2200 个微服务分类为 70 个域。其中大约 50% 已经实施,其中大多数都有一些未来采用的计划。
Future Migrations 未来的迁移
At Uber, we calculated that the half-life of a microservice was 1.5 years, which means that every 1.5 years 50% of our microservices churn. Without gateways it’s easy for a microservice architecture to fall into a “migration hell” as a result of this churn.
在 Uber,我们计算出微服务的半衰期是 1.5 年,这意味着每 1.5 年我们就有 50% 的微服务流失。如果没有网关,微服务架构很容易因这种流失而陷入“迁移地狱”。
Ever changing microservices constantly require upstream migrations. Gateways enable teams to avoid dependencies on the underlying domain services, which means those services can change without forcing an upstream migration.
不断变化的微服务不断需要上游迁移。网关使团队能够避免对底层域服务的依赖,这意味着这些服务可以在不强制上游迁移的情况下进行更改。
Two of Uber’s largest platform rewrites in the last year happened behind gateways. These platforms had hundreds of services that depended on them that would have had to migrate existing consumers.
去年,Uber 最大的两次平台重写都发生在网关后面。这些平台有数百项依赖于它们的服务,而这些服务必须迁移现有的消费者。
The cost of migration in these cases would have been extremely high, making a complete platform rewrite infeasible.
在这些情况下,迁移成本将非常高,使得完整的平台重写变得不可行。
New Lines of Business & Products
新业务和新产品
Platforms designed using DOMA have proven to be much more extensible and easier to maintain. Most teams at Uber who adopted DOMA did so because supporting new lines of business had become too expensive.
事实证明,使用 DOMA 设计的平台具有更高的可扩展性并且更易于维护。 Uber 的大多数团队采用 DOMA 都是因为支持新业务线的成本太高。
Practical Advice 实用建议
This section provides some practical advice for companies that might want to adopt DOMA. The guiding principle here is that in our experience a mature and thoughtful microservice architecture stems from quiet nudges in the right direction at the right time.
本节为可能想要采用 DOMA 的公司提供一些实用建议。这里的指导原则是,根据我们的经验,成熟且周到的微服务架构源于在正确的时间向正确的方向悄悄推动。
The reality is that a true “rewrite” is never possible for one’s entire microservice architecture.
现实情况是,对于整个微服务架构来说,真正的“重写”是不可能的。
As a result, we think of evolving a microservice architecture more like “trimming a hedge” so that it eventually grows correctly, rather than a top-down or one-time architecture (or re-architecture) effort. It’s a dynamic and progressive process.
因此,我们认为发展微服务架构更像是“修剪树篱”,以便它最终正确增长,而不是自上而下或一次性架构(或重新架构)工作。这是一个动态且渐进的过程。
Startups 初创公司
The driving questions should be “when should we adopt a microservice architecture?” and “does it make sense for our organization?” As we’ve seen above, while microservices provide an operational benefit to organizations with a large number of engineers, this trades off with an increase in complexity that can make features more difficult to build.
驱动问题应该是“我们什么时候应该采用微服务架构?”以及“这对我们的组织有意义吗?”正如我们在上面所看到的,虽然微服务为拥有大量工程师的组织提供了运营优势,但这会增加复杂性,从而使功能更难构建。
In small organizations, the operational benefit likely does not offset the increase in architectural complexity.
在小型组织中,运营收益可能无法抵消架构复杂性的增加。
Furthermore, microservice architectures often require dedicated engineering resources to support which may be out of budget for an early stage company or else suboptimal from a prioritization perspective.
此外,微服务架构通常需要专用的工程资源来支持,这对于早期阶段的公司来说可能超出预算,或者从优先级的角度来看不是最理想的。
With this in mind, it isn’t unreasonable to hold off on microservices altogether for some time.
考虑到这一点,完全推迟一段时间微服务并不是没有道理的。
If an organization does choose to adopt microservices, it should think about the “microservice as large distributed application” analogy, and the separation of concerns between microservices it wants to build.
如果一个组织确实选择采用微服务,它应该考虑“微服务作为大型分布式应用程序”的类比,以及它想要构建的微服务之间的关注点分离。
Also, recognize that the first microservices will likely be the most important and longest lasting as they truly describe the core of the business.
此外,要认识到第一个微服务可能是最重要和最持久的,因为它们真正描述了业务的核心。
Midsize 中号
Once a company becomes midsized with multiple teams and the clear separation of concerns becomes hazy between different features and platforms, microservice architectures become more obviously useful.
一旦公司成为拥有多个团队的中型企业,并且不同功能和平台之间的关注点明确分离变得模糊,微服务架构就会变得更加有用。
It’s at this stage that one can begin to think about hierarchies between microservices. Dependency management may become more important, as some services begin to become more obviously critical to business operation, and more and more teams rely on them.
在这个阶段,人们可以开始考虑微服务之间的层次结构。依赖管理可能会变得更加重要,因为某些服务开始对业务运营变得更加明显重要,并且越来越多的团队依赖它们。
Early investment in platformization may pay dividends down the road. There is the possibility to avoid tech debt here if one can create completely product agnostic business platforms and avoid arbitrary product logic in core platform services.
对平台化的早期投资可能会在未来带来回报。如果能够创建完全与产品无关的业务平台并避免核心平台服务中的任意产品逻辑,则有可能避免技术债务。
It might make sense to adopt extensions at this point to accomplish that goal.
此时采用扩展来实现该目标可能是有意义的。
Given that the number of microservices is likely still quite low, it may not make sense to cluster them together.
鉴于微服务的数量可能仍然很低,将它们聚集在一起可能没有意义。
However, it’s worth noting here that a domain in the context of Uber’s DOMA implementation can contain a single service, so it may still be useful to think in a “domain-oriented” way.
然而,这里值得注意的是,Uber DOMA 实现上下文中的域可以包含单个服务,因此以“面向域”的方式思考可能仍然有用。
Large 大的
Larger engineering organizations may have hundreds of engineers and microservices and several dependencies. At this point DOMA reaches its full usefulness.
较大的工程组织可能拥有数百名工程师和微服务以及多个依赖项。至此,DOMA 就充分发挥了作用。
There will likely be obvious clusters of microservices that can be easily grouped together into domains with a gateway in front of them.
可能会有明显的微服务集群,可以轻松地将它们分组到前面有网关的域中。
Legacy services often begin to need to be refactored or rewritten and then migrated, which means that gateways will soon begin to provide value in terms of ease of migration if they are already in place.
遗留服务通常开始需要重构或重写,然后进行迁移,这意味着网关如果已经就位,很快就会开始在易于迁移方面提供价值。
Clear hierarchy will also become increasingly important with some services operating as “product” services for particular features or grouping of features, and other services will increasingly support multiple products and be thought of as “platforms.” It’s critical at this stage to keep arbitrary product logic decoupled from platforms, so as to avoid a heavy operational burden on platform teams as well as system-wide instability.
清晰的层次结构也将变得越来越重要,因为某些服务作为特定功能或功能分组的“产品”服务运行,而其他服务将越来越多地支持多种产品并被视为“平台”。在这个阶段,保持任意产品逻辑与平台解耦至关重要,以避免平台团队沉重的运营负担以及系统范围的不稳定。
Final Thoughts 最后的想法
We are still actively evolving DOMA as more and more teams at Uber come to adopt it.
随着 Uber 越来越多的团队开始采用 DOMA,我们仍在积极发展 DOMA。
The critical insight of DOMA is that a microservice architecture is really just one, large, distributed program and you can apply the same principles to its evolution that you would apply to any piece of software.
DOMA 的关键见解是,微服务架构实际上只是一个大型分布式程序,您可以将应用于任何软件的相同原则应用于其演进。
DOMA is simply an approach for thinking about these principles in practice. We hope others find it useful and we look forward to feedback!
DOMA 只是在实践中思考这些原则的一种方法。我们希望其他人发现它有用,我们期待反馈!
DOMA itself was the result of a cross-functional effort, which involved nearly 60 engineers across every org at Uber. Some particular acknowledgements, for people who invested heavily into this effort over the last 2 years…
DOMA 本身是跨职能努力的结果,涉及 Uber 每个组织的近 60 名工程师。对于过去 2 年来在这项工作上投入巨资的人们,我们要特别致谢……
Alex Zylman, Alexandre Wilhelm, 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, Joshua Shinavier, Julia Law, Kusha Kapoor, Linda Fu, Madan Thangavelu, Nimish Sheth, Parth Shah, Shawn Burke, Simon Newton, Steve Sherwood, Uday Kiran Medisetty, and Waleed Kadous
亚历克斯·齐尔曼、亚历山大·威廉、艾伦·陆、安基特·斯里瓦斯塔瓦、安东尼·特兰、阿努潘·迪克希特、阿努拉格·比亚尼、丹尼尔·沃尔夫、大卫·达戈斯蒂诺、迪普蒂·切达、德米特里·布林丁、Gaurav Tungatkar、雅各布·格林利夫、Jaikumar Ganesh、Jennie Ngyuen、Joe McCabe、 Joshua Shinavier、Julia Law、Kusha Kapoor、Linda Fu、Madan Thangavelu、Nimish Sheth、Parth Shah、Shawn Burke、Simon Newton、Steve Sherwood、Uday Kiran Medisetty 和 Waleed Kadous
Acknowledgements: 致谢:
This work brings multiple existing design patterns in the industry to solve problems at Uber while also suggesting new patterns like extensions. We are thankful to the industry for the work on them. We are also thankful to the engineers at Linkedin who worked on Superblocks, who spoke to us about their experiences.
这项工作引入了业界现有的多种设计模式来解决 Uber 的问题,同时还提出了扩展等新模式。我们感谢业界在这些方面所做的工作。我们还感谢在 Superblocks 工作的 Linkedin 工程师,他们向我们讲述了他们的经历。
Adam Gluck 亚当·格鲁克
Adam Gluck is a Sr. Software Engineer II at Uber. He spent his first 3.5 years at Uber fleshing out our Driver Platform team and helping to scale our driver product.
Adam Gluck 是 Uber 的高级二级软件工程师。他在 Uber 工作的头 3.5 年充实了我们的司机平台团队,并帮助扩展了我们的司机产品。
More recently, he’s been a part of Uber’s engineering strategy team, focused on high level system architecture and Uber-wide platformization efforts.
最近,他成为 Uber 工程战略团队的一员,专注于高级系统架构和 Uber 范围内的平台化工作。
Posted by Adam Gluck 亚当·格鲁克发表
Related articles 相关文章
Most popular 最受欢迎
工程、后端 6 月 18 日/全球
Debugging with Production Neighbors – Powered by SLATE
与生产邻居一起调试 – 由 SLATE 提供支持
工程、后端 6 月 20 日/全球
How Uber ensures Apache Cassandra®’s tolerance for single-zone failure
Uber 如何确保 Apache Cassandra® 对单区域故障的容忍度
工程 6 月 27 日/全球
Modernizing Logging at Uber with CLP (Part II)
使用 CLP 实现 Uber 日志记录现代化(第二部分)
工程、数据 / ML7 月 1 日 / 全球