跨微服务共享DTO的方法?


33

我的情况如下。

我正在设计一个系统,该系统旨在从各种类型的传感器接收数据,然后进行转换并将其持久化,以供以后的各种前端和分析服务使用。

我正在尝试将每个服务设计为尽可能独立,但是遇到了一些麻烦。团队已决定要使用的DTO。面向外部的服务(传感器数据接收者)将以自己独特的方式接收数据,然后将其转换为JSON对象(DTO)并将其发送给Message Broker。消息的使用者将确切地知道如何读取传感器数据消息。

问题是我在几个不同的服务中使用了相同的DTO。必须在多个位置实施更新。显然,我们的设计方式使得此处的DTO中有一些多余或缺失的字段,并且在更新服务之前不会有太大的问题,但这仍然困扰着我,并使我感到自己犯错误。它很容易变成头痛。

我在设计系统时会出错吗?如果没有,那么有什么解决办法,或者至少可以缓解我的担心?


您共享哪种DTO,服务之间使用哪种协议?可以共享例如protogRPC 的文件或avroKafka 的架构并在两个服务中生成DTO,但是我不会在两个项目之间共享共享库。
Vincent Savard '18

编码的JSON字符串和AMQP。我宁愿不使用任何特定于语言的内容。
nbaughman

Answers:


38

我的建议?不要在任何类型的库的应用程序之间共享这些DTO。或者至少现在不要这样做。

我知道,似乎很违反直觉。您正在复制代码,对吗?但这不是业务规则,因此您可以更加灵活。

发送DTO的服务必须严格遵守其消息合同,例如Rest API。该服务不能以可能破坏其他已经使用了DTO信息的其他服务的方式更改DTO。

当一个新的领域时,请勿DTO加入,你只更新消耗这DTO的其他服务,如果他们需要的新领域。否则,算了吧。使用JSON作为内容类型,您可以灵活地创建和发送新属性,而不会中断不会将这些新字段映射到他的实际DTO版本上的服务的代码。

但是,如果这种情况确实使您感到困扰,则可以遵循三法则

重用有两个“三规则”:(a)构建可重用组件的难度是一次性组件的三倍;(b)在足够通用之前,应在三个不同的应用程序中试用可重用组件。接受到重用库中。

因此,在服务之间共享此DTO之前,请尝试稍等。


1
非常感谢。这确实是我今后要解决的几个主要问题之一。不足以让我彻夜难眠,但足以让我担心。
nbaughman

4
重复的DTO(在不同且非常独立的服务中)不会违反DRY。而已。
Laiv

3
大概没有理由不将DTO源代码直接从一个项目复制到另一个项目中,这是一项一次性的操作,尽管这时应该删除新项目中不需要的任何部分。
bdsl

1
甚至整个服务都可能被删除,不会对整个系统造成重大问题。理想地。
Laiv

4
为了阐明答案的实质,在开发微服务时,应该将每个服务开发为好像它们对其他服务一无所知,除了可能需要的实际合同。
Jonathan van de Veen

12

当涉及微服务时,服务的开发生命周期也应该是独立的。*

不同的SLDC和不同的开发团队

在实际的MS系统中,可能有多个团队参与生态系统的开发,每个团队负责一项或多项服务。反过来,这些团队可能位于不同的办公室,城市,国家/地区,计划……也许,他们甚至彼此都不认识,这使得共享知识或代码变得非常困难(如果可能)。但这可能非常方便,因为共享代码还暗含一种共享推理,并且需要记住的重要一点是,对于特定团队而言,有意义的是,不必为另一个团队使用。例如,给定DTO Customer,根据所使用的服务,它可能会有所不同,因为对客户的解释(或看到)与每种服务不同。

不同的需求,不同的技术

隔离的SLDC还允许团队选择最适合其需求的堆栈。强加于特定技术中的DTO限制了团队的选择能力。

DTO既不是业务规则也不是服务合同

真正的DTO是什么?普通对象没有其他目标,只能将数据从一侧移动到另一侧。吸气剂和装袋机袋。总体而言,这不是值得重复使用的“知识”,因为根本没有知识。它们的波动性也使它们不适合耦合。

与Dherik所说的相反,服务必须有可能更改其DTO,而不必同时更改其他服务。服务应该宽容的读者,宽容的作家和不能容忍的。否则,它们将导致耦合,从而使服务体系结构变得毫无意义。再一次,与Dherik的回答相反,如果三个服务需要完全相同的DTO,则在服务分解期间可能出了点问题。

不同的业务,不同的解释

虽然服务之间可能存在(并且将会有)跨领域的概念,但这并不意味着我们必须强加规范的模型来强制所有服务以相同的方式解释它们。

案例分析

假设我们公司有三个部门,即客户服务销售运输部门。说每个发行一个或多个服务。

客户服务由于其领域语言而围绕客户的概念(客户人)实施服务。例如,客户被建模为姓名姓氏年龄性别电子邮件电话等。

现在说,“ 销售运输”也根据它们各自的域语言对服务进行建模。在这些语言中,概念客户也出现了,但有细微的差别。对他们而言,客户 不是(不一定)。对于 销售,客户有一个文件号码一个信用卡账单地址,为航运一个全名送货地址了。

如果我们强迫销售运输部门采用客户服务的规范数据模型,那么我们将迫使他们处理不必要的数据,如果他们必须维护整体表示并使客户数据与客户服务保持同步,则最终可能导致不必要的复杂性。。

相关链接


*这是此架构的优势所在


谢谢!案例研究实际上是帮助我确定是否共享DTO的原因。现在,我可以确定为什么我不想共享它们。
伊戈尔

8

我正在尝试将每项服务设计为尽可能独立

您应该发布事件。事件是某些类型的消息,表示在特定时间点发生的某些事情的确凿事实

每个服务应具有明确定义的职责,并应负责发布与该职责相关的事件。

此外,您希望事件代表业务相关事件,而不是技术事件。例如,喜欢OrderCancelled事件的OrderUpdatedstatus: "CANCELLED"

这样,当服务需要对已取消的订单做出反应时,它只需要侦听特定类型的消息,该消息仅携带与该事件相关的数据。例如,OrderCancelled可能只需要一个order_id。对此需要做出反应的任何服务都已经在其自己的数据存储中存储了需要了解的订单信息。

但是,如果服务仅具有OrderUpdated要监听的事件,则它需要解释事件的流程,并且当订单被取消时,它现在依赖于交付订单来正确地得出结论。

在你的情况,但是,由于你要发布传感器数据,它可能是有意义的有一个服务,听取事件和发布“商业事件”,例如新的流TemperatureThresholdExceededTemperatureStabilised

并且要注意创建太多的微服务。微服务可能是封装复杂性的一种好方法,但是如果您没有找到合适的服务边界,那么复杂性就在于服务集成。这就是一场噩梦。

拥有太少,太大的服务比拥有太多,太小的服务要好。


我绝对同意。传感器数据直接进入微服务,该微服务解析消息并将其转换为组织范围内同意的格式,然后再发布给代理。我们将提供一些服务来读取消息并将其持久化到数据库中,还有一些服务将对消息进行分析并对其做自己的事情。根据业务的性质,每种服务都没有太多要做,因此(希望)提供非常简单的服务。
nbaughman

2
@ Nickdb93-在您的情况下,由于您正在发布传感器数据,因此有必要提供服务,收听事件并发布新的“业务事件”流,例如TemperatureThresholdExceeded,TemperatureStabilized。(添加答案)
皮特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.