简体   繁体   English

如何在微服务中使用干净的架构?

[英]How to use Clean Architecture in Microservices?

I just finished reading Uncle Bob's "Clean Architecture" and now wondering how to apply it in the context of microservices!我刚读完鲍勃叔叔的“清洁架构”,现在想知道如何在微服务的上下文中应用它!

On one hand, I think that microservices fall in the "Framework-Drivers" layer since it's an implementation on top of use-cases (they are ways to serve use-cases.) This way, we focus on the core of the app (Entities and Use-cases) and stay flexible in the implementation of the outer layers (including microservices).一方面,我认为微服务属于“框架驱动”层,因为它是在用例之上的实现(它们是服务用例的方式。)这样,我们专注于应用程序的核心(实体和用例)并在外层(包括微服务)的实现中保持灵活性。 But since each microservice can be maintained by a different developer/team of developers, they will have a bad time when use-cases change (harder to predict who will be impacted).但是由于每个微服务都可以由不同的开发人员/开发人员团队维护,因此当用例发生变化时,他们将度过一段糟糕的时光(更难预测谁会受到影响)。

On the other hand, we can split our app into multiple microservices, decoupled from each other, and apply Clean Architecture inside each microservice.另一方面,我们可以将我们的应用程序拆分为多个微服务,彼此解耦,并在每个微服务中应用清洁架构。 The pro of this approach is that we can focus on each microservice doing one thing, and doing it well.这种方法的优点是我们可以专注于每个微服务做一件事,并且做得很好。 But the problem is that we started designing using technical separations (microservices) which violates the main Clean Architecture principle of focusing on the business.但问题是我们开始使用技术分离(微服务)进行设计,这违反了专注于业务的主要清洁架构原则。 Also, it will be hard to not duplicate code if two microservices uses the same entity or use-case!此外,如果两个微服务使用相同的实体或用例,很难不重复代码!

I think the first scenario is the best, but I would like to have feedback from fellow developers on the long-term benefits of both scenarios, and potential troubles.我认为第一种方案是最好的,但我想从开发人员那里获得关于这两种方案的长期利益和潜在问题的反馈。

As @lww-pai-long said in his answer here splitting based on the Domain responsibilities and DDD is in most cases the best solution.正如@lww-pai-long 在他的回答中所说,根据域职责进行拆分,DDD 在大多数情况下是最好的解决方案。 Still if you worked with a system using micro-services you soon realize that there are other things involved here as well.尽管如此,如果您使用微服务的系统工作,您很快就会意识到这里还涉及其他事情。

DDD Bounded Context as base for micro-services DDD 有界上下文作为微服务的基础

In most cases splitting your application to micro-services based on Bounded Context is the safe way to go here.在大多数情况下,基于限界上下文将您的应用程序拆分为微服务是 go 的安全方法。 From experience I would even say that in some parts of Domain you could go even further and have multiple micro-services per Bounded Context.根据经验,我什至会说,在域的某些部分中,您可以更进一步地使用 go,并且每个限界上下文具有多个微服务。 Example would be if you have quite big part of Domain which represents one Bounded Context.例如,如果您有相当大部分的域代表一个有界上下文。 Other example would be if you use CQRS for a particular Domain.其他示例是,如果您将 CQRS 用于特定域。 Then you can end up having a Write/Domain and Views/Read micro-service.然后你可以最终拥有一个写入/域和视图/读取微服务。 You can read in this answer how you can split your Domain to micro-services.您可以在此答案中阅读如何将您的域拆分为微服务。 It would be advisable as you said to "apply Clean Architecture inside each microservice".正如您所说,建议“在每个微服务中应用清洁架构”。

Also, it will be hard to not duplicate code if two microservices uses the same entity or use-case!此外,如果两个微服务使用相同的实体或用例,很难不重复代码!

This is something that you have to deal with when working with micro-services in most cases.在大多数情况下,这是您在使用微服务时必须处理的事情。 Duplicating code and/or data across multiple micro-service is common drawback of working with micro-services.跨多个微服务复制代码和/或数据是使用微服务的常见缺点。 You have to take this into account as you on the other hand get isolation and independence of the micro-service and its database.您必须考虑到这一点,因为另一方面您要获得微服务及其数据库的隔离和独立性。 This problem can be partly solved by using shared libraries as some sort of packages.这个问题可以通过使用共享库作为某种包来部分解决。 Be careful this is not the best approach for all cases.请注意,这不是适用于所有情况的最佳方法。 Here you can read about using common code and libraries across micro-services.在这里,您可以阅读有关在微服务中使用通用代码和库的信息。 Unfortunately not all advice's and principles from Uncle Bob's "Clean Architecture" can be applied when using micro-services.不幸的是,在使用微服务时,并非鲍勃叔叔的“清洁架构”中的所有建议和原则都可以应用。

Non Domain or technical operation micro-services非领域或技术运营微服务

Usually if your solution is using micro-services you will more or less have micro-services which are not Domain specific but rather some kind of technical task's or non business operations directly.通常,如果您的解决方案使用微服务,您将或多或少拥有不是特定于域的微服务,而是直接用于某种技术任务或非业务操作的微服务。 Example could be something like:示例可能类似于:

  • micro-service for report generation用于生成报告的微服务
  • micro-service for email generation and forwarding email 生成和转发的微服务
  • micro-service for authorization/permission management用于授权/权限管理的微服务
  • micro-service for secret management用于秘密管理的微服务
  • micro-service for notification management通知管理微服务

These are not services which you will get by splitting your solution based on DDD principles but you still need them as general solution as they could be consumed by multiple other services.这些不是您通过基于 DDD 原则拆分您的解决方案所获得的服务,但您仍然需要它们作为通用解决方案,因为它们可以被多个其他服务使用。

Conclusion结论

When working with micro-services you will most of the time have a mixture of Domain specific and Domain agnostic micro-services.在使用微服务时,大多数时候您将混合使用特定于域的微服务和与域无关的微服务。 I think the Clean Architecture could be looked from a little different prospective when working with micro-services.我认为在使用微服务时,可以从一个稍微不同的角度看待清洁架构。

On one hand, I think that microservices fall in the "Framework-Drivers" layer since it's an implementation on top of use-cases (they are ways to serve use-cases.)一方面,我认为微服务属于“框架驱动”层,因为它是在用例之上的实现(它们是服务用例的方式。)

It kind of does but it also falls into the other layers like Entities and Use Cases.确实如此,但它也属于其他层,例如实体和用例。 I think it goes in the direction that if you work on Domain specific services this Diagram becomes the Architecture of each micro-service but not a concept above all micro-services.我认为它的方向是,如果你在特定领域的服务上工作,这个就变成了每个微服务的架构,但不是所有微服务之上的概念。 In the applications where I worked with micro-services each micro-service(the ones which are based on the DDD Bounded Context) had most of this layers if not all of them.在我使用微服务的应用程序中,每个微服务(基于 DDD 有界上下文的微服务)如果不是全部,也有大部分。 The Domain agnostic services are an exception to this as they are not based on Domain Entities but rather on some tasks or operations like 'Create an Email', 'Create a PDF report from html template' or similar'.与域无关的服务是一个例外,因为它们不是基于域实体,而是基于某些任务或操作,例如“创建电子邮件”、“从 html 模板创建 PDF 报告”或类似内容。

I think this question may be better on Sofware Engineering but I'll answer anyway.我认为这个问题在软件工程上可能会更好,但无论如何我都会回答。


My approach would be to use DDD and define each microservice as a Domain Services grouping Use Cases semantically, then link Domain Services with Bounded Context .我的方法是使用 DDD 并将每个微服务定义为语义上对用例进行分组的域服务,然后将域服务Bounded Context链接。

Sam newman talk about the importance of separating microservice by domain abraction and not technical one in Building Microservices Sam newman 在构建微服务中谈到了通过域分离而不是技术分离微服务的重要性

The point he makes basically is that defining scaling strategies for microservice based on subdomain will better match the "real live" contraints observed on the production system than using technically based microservice and try to defined a abstract straetegy.他的观点基本上是,基于子域定义微服务的扩展策略将比使用基于技术的微服务并尝试定义抽象策略更好地匹配在生产系统上观察到的“实时”约束。

And if you look at how something like Kubernetes works it seems to push to that direction.如果你看看像 Kubernetes 这样的东西是如何工作的,它似乎会朝着这个方向发展。 A pod end up being a microservice with multiple containers defined as a complete stack matching a sub-domain if the overhaul application.一个pod最终成为一个微服务,其中包含多个容器,如果是大修应用程序,则定义为一个与子域匹配的完整堆栈。

It then gets easier in an e-commerce application, for example, to scale the Payment service independently of the Cart service based on customer activity than to scale the web services independently of the job queues in an abstract way.然后在电子商务应用程序中变得更容易,例如,根据客户活动独立于购物车服务扩展支付服务,而不是以抽象方式独立于作业队列扩展 web 服务。

The way those Bounded Contexts will communicate, ie request based or event based , depends on the the specific relation between them.这些限界上下文的通信方式,即基于请求或基于事件,取决于它们之间的具体关系。 To use the same example a Cart may generate an event that will trigger the Payment , while the same Cart may need to request the Inventory before validating the order.使用相同的示例,购物车可能会生成将触发付款的事件,而同一购物车可能需要在验证订单之前请求库存

And at the end of a day those Domain Services* and Bounded Contexts can be implemented the same when starting with a monolith, even the Bounded Contexts communication can be.归根结底,那些域服务*和限界上下文可以在从单体应用开始时以相同的方式实现,甚至限界上下文通信也可以。 The underlying communication protocol becomes an implementation detail that can easily(kinda) be switch when transitioning to a distributed aka microservices architecture.底层通信协议成为实现细节,在转换到分布式又名微服务架构时可以轻松(有点)切换。

My two cents:我的两分钱:

From Uncle Bob's words , "Micro-services are deployment option, not an architecture".用 Bob 大叔的话来说,“微服务是部署选项,而不是架构”。 Each micro-service should be deployable, maintainable by different teams (which can be in different geographical locations).每个微服务都应该由不同的团队(可以在不同的地理位置)部署和维护。 Each team can choose their own architecture, programming language, tools, frameworks etc... And forcing each team to use single/same programming language or tool or architecture does not sound good.每个团队都可以选择自己的架构、编程语言、工具、框架等……而强迫每个团队使用单一/相同的编程语言或工具或架构听起来并不好。 So each micro-service team must be able to pick their architecture.所以每个微服务团队必须能够选择他们的架构。

How can each team code/maintain/deploy their own micro-service without conflicting with other teams code?每个团队如何在不与其他团队代码冲突的情况下编写/维护/部署自己的微服务? This question brings us to how to separate micro-services.这个问题给我们带来了如何分离微服务。 IMHO it should be separated on feature based (same principle applies to modularization of mobile application projects where independent teams should be able to work on separate modules/micro-services).恕我直言,它应该基于功能分开(同样的原则适用于移动应用程序项目的模块化,其中独立团队应该能够处理单独的模块/微服务)。

After separating micro-services, the communication between them is implementation detail.分离微服务后,它们之间的通信就是实现细节。 It can be done through web-socket/REST API etc... Inside each micro-service, if team decides to follow Clean Architecture, they can have multiple layers based on Clean Arch Principles (Domain/Core - Interface Adapters - Presentation/API & Data & Infrastructure).它可以通过 web-socket/REST API 等来完成......在每个微服务内部,如果团队决定遵循清洁架构,他们可以根据清洁架构原则(域/核心 - 接口适配器 - 表示/API)拥有多个层& 数据 & 基础设施)。 There can/will be duplicate codes on micro-services, which are OK for micro-services.微服务上可以/将会有重复的代码,这对于微服务来说是可以的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM