【问题标题】:How to use Clean Architecture in Microservices?如何在微服务中使用干净的架构?
【发布时间】:2020-03-10 16:06:05
【问题描述】:

我刚读完鲍勃叔叔的“清洁架构”,现在想知道如何在微服务的上下文中应用它!

一方面,我认为微服务属于“框架驱动”层,因为它是在用例之上的实现(它们是服务用例的方式)。这样,我们专注于核心应用程序(实体和用例)并在外层(包括微服务)的实现中保持灵活性。但是,由于每个微服务都可以由不同的开发人员/开发团队维护,因此当用例发生变化时,他们会遇到麻烦(更难预测谁会受到影响)。

另一方面,我们可以将应用拆分为多个微服务,彼此解耦,并在每个微服务中应用清洁架构。这种方法的优点是我们可以专注于每个微服务做一件事,并且做得很好。但问题是我们开始使用技术分离(微服务)进行设计,这违反了专注于业务的主要清洁架构原则。此外,如果两个微服务使用相同的实体或用例,很难不重复代码!

我认为第一种方案是最好的,但我想从开发人员那里获得关于这两种方案的长期利益和潜在问题的反馈。

【问题讨论】:

    标签: microservices clean-architecture


    【解决方案1】:

    正如@lww-pai-long 在他的回答中所说,根据域职责进行拆分,DDD 在大多数情况下是最好的解决方案。 不过,如果您使用的是使用微服务的系统,您很快就会意识到这里还涉及其他事情。

    DDD 限界上下文作为微服务的基础

    在大多数情况下,基于限界上下文将您的应用程序拆分为微服务是安全的方法。根据经验,我什至会说,在 Domain 的某些部分,你可以走得更远,每个限界上下文有多个微服务。例如,如果您有相当大部分的域代表一个有界上下文。其他示例是,如果您将 CQRS 用于特定域。然后你可以最终拥有一个写入/域和视图/读取微服务。 您可以在此answer 中阅读如何将您的域拆分为微服务。 正如您所说,建议“在每个微服务中应用干净的架构”。

    另外,如果两个微服务使用,很难不重复代码 相同的实体或用例!

    这是在大多数情况下使用微服务时必须处理的问题。跨多个微服务复制代码和/或数据是使用微服务的常见缺点。您必须考虑到这一点,因为另一方面您要获得微服务及其数据库的隔离和独立性。这个问题可以通过使用共享库作为某种包来部分解决。请注意,这不是适用于所有情况的最佳方法。 Here 您可以阅读有关在微服务中使用通用代码和库的信息。不幸的是,在使用微服务时,并非鲍勃叔叔的“清洁架构”中的所有建议和原则都可以应用。

    非领域或技术运营微服务

    通常,如果您的解决方案使用微服务,您将或多或少拥有非特定领域的微服务,而是直接用于某种技术任务或非业务操作。示例可能是这样的:

    • 报告生成微服务
    • 用于电子邮件生成和转发的微服务
    • 用于授权/权限管理的微服务
    • 用于秘密管理的微服务
    • 通知管理微服务

    这些不是您可以通过基于 DDD 原则拆分解决方案获得的服务,但您仍然需要将它们作为通用解决方案,因为它们可以被多个其他服务使用。

    结论

    在使用微服务时,您大部分时间都会混合使用特定于域的微服务和与域无关的微服务。我认为在使用微服务时,可以从不同的角度看待 Clean Architecture。

    一方面,我认为微服务属于 “Framework-Drivers”层,因为它是在 用例(它们是服务用例的方式。)

    确实如此,但它也属于实体和用例等其他层。我认为它的方向是,如果你在特定领域的服务上工作,这个Diagram 成为每个微服务的架构,但不是所有微服务之上的概念。在我使用微服务的应用程序中,每个微服务(基于 DDD 有界上下文的微服务)如果不是全部,也有大部分。与域无关的服务是一个例外,因为它们不是基于域实体,而是基于某些任务或操作,例如“创建电子邮件”、“从 html 模板创建 PDF 报告”或类似的。

    【讨论】:

    • 我同意域服务有时值得在子域中再次拆分。我也同意代码或库的可能重复是不可避免的权衡,在最坏的情况下可能成为依赖地狱盛宴。但是关于非域或辅助功能,恕我直言,这些服务也可以实现为边车,即由application operator 添加,因为到处都需要,这样它们仍然可以根据域服务活动进行扩展。
    【解决方案2】:

    我的两分钱:

    来自 Bob 大叔的 words,“微服务是部署选项,而不是架构”。每个微服务都应该由不同的团队(可以在不同的地理位置)部署和维护。每个团队都可以选择自己的架构、编程语言、工具、框架等... 强制每个团队使用单一/相同的编程语言或工具或架构听起来并不好。所以每个微服务团队必须能够选择他们的架构。

    每个团队如何在不与其他团队代码冲突的情况下编写/维护/部署自己的微服务?这个问题给我们带来了如何分离微服务。恕我直言,它应该基于功能分开(同样的原则适用于移动应用程序项目的模块化,其中独立团队应该能够处理单独的模块/微服务)。

    分离微服务后,它们之间的通信就是实现细节。它可以通过 web-socket/REST API 等来完成......在每个微服务中,如果团队决定遵循 Clean Architecture,他们可以根据 Clean Arch 原则(域/核心 - 接口适配器 - 表示/API)拥有多个层& 数据 & 基础设施)。微服务上可以/将会有重复的代码,这对于微服务来说是可以的。

    【讨论】:

      【解决方案3】:

      我认为这个问题在Sofware Engineering 上可能会更好,但我还是会回答。


      我的方法是使用 DDD 并将每个微服务定义为 Domain Services 在语义上对 Use Cases 进行分组,然后将 Domain Services 与 限界上下文。

      Sam newman 在Building Microservices 中谈到了通过域分离而不是技术分离微服务的重要性

      他的观点基本上是,与使用基于技术的微服务并尝试定义抽象策略相比,基于子域定义微服务的扩展策略将更好地匹配在生产系统上观察到的“实时”约束。

      如果你看看像 Kubernetes 这样的东西是如何工作的,它似乎会朝着这个方向发展。 pod 最终成为一个微服务,其中包含多个容器,如果是大修应用程序,则定义为与子域匹配的完整堆栈。

      然后在电子商务应用程序中变得更容易,例如,根据客户活动独立于 Cart 服务扩展 Payment 服务,而不是扩展 Web以抽象的方式独立于作业队列的服务。

      这些限界上下文的通信方式,即基于请求或基于事件,取决于它们之间的具体关系。要使用相同的示例,Cart 可能会生成将触发 Payment 的事件,而相同的 Cart 可能需要请求 在验证订单之前清点

      在一天结束时,那些域服务* 和 限界上下文 可以在从单体应用开始时以相同的方式实现,甚至可以实现 限界上下文 通信。底层通信协议变成了一个实现细节,在过渡到分布式(又名)微服务架构时可以轻松(有点)切换。

      【讨论】:

        猜你喜欢
        • 2014-01-08
        • 2022-05-28
        • 1970-01-01
        • 2018-10-09
        • 2019-03-28
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        • 2015-12-26
        相关资源
        最近更新 更多