在微服务之间共享DTO对象


15

TL; DR-可以在服务之间共享POJO库吗?

通常,如果可能的话,我们希望将服务之间的共享严格限制为无共享。共享数据的服务是否应提供客户端库供客户端使用一直存在争议。客户端库通常对于服务的客户端是可选的,并且可以使用API​​,但是无论他们愿意使用API​​,还是使用客户端库还是使用替代语言并使用库的一般方面,等等。

就我而言-我考虑一种创建数据对象的服务。假设此对象是PET。不是数据库实体,而是严格地隐式表示基础数据的POJO。该POJO是API定义的。假设:宠物-年龄,体重,姓名,所有者,地址,种类等。

服务1 -PetKeeper:无论出于何种原因,它都会生成一个pet,并保留所有数据,并且必须引用此服务来获取pet,或者对pet进行修改,可以说名称更改或地址更改必须通过以下方式完成:此服务的API调用。

服务2 -PetAccessor:此服务收集宠物并进行验证检查

服务3,4-更多中间服务呼叫

服务5-用户界面

这些都是很随意的,但重点很简单。UI或某些面向用户的服务希望以某种方式呈现此“ PET”对象。它必须通过API调用一个服务,该服务调用一个服务,再调用一个服务,依此类推,直到到达收集所需信息并开始中继的服务为止。最后,UI服务具有要显示的PET对象。

这很普遍-但出于我们的绝对思想,我们在每次服务中都复制了PET对象。DRY(请勿重复)原则仅适用于服务内的代码,不适用于所有服务,但重点仍然存在。如果我们添加一个字段怎么办...我们必须在每个字段中修改POJO的5个服务。

-或-我们可以提供一个Pet-Objects-Library,其中包含API中的一些pojo,并且每个服务都可以导入/依赖该库。与服务本身无关,而与常规库无关。我喜欢这个想法,以便每个服务都具有相同类型的对象,并且更新更加容易。但是我担心神物。

优点/缺点是什么-最佳设计是什么?您做了什么在服务之间传递数据,以最大程度地减少重复执行相同的POJO类,同时保持解耦状态?



@DaiKaixian:当然,您不是在暗示 OP带有上帝的对象,是吗?通常将其视为反模式。
Makoto

我同意@javaguy的回答。

我也想说,您可以考虑使用访客模式。en.wikipedia.org/wiki/Visitor_pattern 。在POJO中创建所有字段和setter / getter,并在微服务之间共享。如果要在不同微服务中的POJO上执行某些操作,请编写一些VisitorClass。

谢谢。我对拥有这个“公共库”感到犹豫,因为它会不断增长。那里的对象中,只有服务1和3关心,或者2和4关心,或者全部关心,或者它们的任何组合。一种通用的DTO库程序包,具有所有DTO,无论我使用vistor模式还是简单的DTO POJO或其他。包括所有这些对象,但尝试尽可能地保持它是否可接受?如果他们希望使用这些物品,至少会把它们提供给需要它们的人...

Answers:


5

最好的设计是什么?

您可以在后端服务(处理典型的业务逻辑)之间重用相同的Pet DTO对象,但是当涉及到表示层(用户界面)时,通常最好使用FormBean(带有附加字段的其他bean)表示逻辑),以便在表示逻辑和业务逻辑之间有明确的区分

这是必需的,因为服务应该是可重用的,并且单个服务可以由多个/不同的终结点(例如前端或可能是不同的Web服务,等等)公开/重用,并且每个终结点都可能需要其他字段,这些字段将由服务上方的各个控制器或层(例如适配器)。

您做了什么在服务之间传递数据,以最大程度地减少重复相同的POJO类,同时保持解耦状态?

如果在业务层和Web层之间使用单个bean,那么您将表示逻辑与业务逻辑紧密结合在一起,这不是一个好习惯,最终您将针对前端中的需求更改服务(例如,不同的日期格式)在用户界面中显示)。另外,要进行跨Bean填充/复制数据的过程(例如DTO到FormBean或Viceversa),可以使用Apache BeanUtils.copyProperties()Dozer之 类的库来避免样板代码


我同意表示层可能应该反序列化传入的负载,作为需要时具有不同属性的表示bean。但是总的来说,可以在所有后端服务中重用相同的DTO对象吗?我们通常会尝试将这些DTO程序包分成较小的程序包,仅用于需要它们的少数服务。我对DTO库软件包的垃圾抽屉感到厌倦,该软件包具有适用于所有服务依赖的75多种微服务的DTO。除非那是可以的,否则首先是DTO对象是可选的吗?

是的,您显然可以在所有类似后端服务中重用相同的DTO对象,PetServices以避免重复。但是我的意思是,不要将后端和前端紧密地结合在一起,仅此而已。
开发人员

4

如果DTO在所有微服务中代表相同的业务实体,则应该只有一个类别,在服务之间共享。对于同一对象重复代码几乎(几乎)是不正确的。


3
跨微服务共享DTO是一场噩梦。“这个版本已经有这个领域了吗?嗯?” 一段时间后,您最终会陷入混乱。在这种情况下,重复代码是好的。
Mejmo '18 -10-25

1

我现在打算这样做的方式是,每个服务仅打包DTO并将其作为jar lib放入Nexus。当其他服务需要这些服务时,它将获得DTO库作为manve / gradle的依赖项。如果新的DTO版本是在一项服务上发布的,则只要同时支持旧版本,它就可以使用,因此不要破坏向后兼容性,版本控制等。因此这是后端到后端的区域。另外,为了防止循环依赖,最好将服务与dto打包分开

现在来看一下后端到前端,反之亦然, 我不同意先前的评论,即作为表示层的UI是不同的。它不是!!! UI只是我的另一个微服务,它也消费和产生事件。

后端到前端的方向 我要做的是将POJO(dtos)转换为Typescript接口,并打包到NPM中,并将它们也加载到Nexus中。然后,基于UI nodejs的项目将使用它们并使用它们。这是UI服务。

从前端到后端的方向对于UI到服务层事件,我将Typescript接口转换为POJOs(dtos),将其打包为jar,然后以jar的形式上传到Nexus(或某些回购库),以供后端服务使用。

这些流程很容易通过CI流程(Travis,Gitlab CI等)进行处理。

欢迎对此方法发表任何评论。

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.