映射 dto/domain 以在微服务之间传输的最佳方法

use*_*472 1 java domain-driven-design dto microservices

我有 DTO 和 DOMAIN 模型:

@Data
public class CarDomain {
    private String name;
    private int year;
    private String color;
}
Run Code Online (Sandbox Code Playgroud)

@Data
public class CarDto {
    private String name;
    private int year;
    private String color;
}
Run Code Online (Sandbox Code Playgroud)

我有 3 个微服务(MS)通过 RabbitMq 相互通信。我有models module所有 DTO 课程。每个 MS 都包含models module 在 maven 中。

1 MS 发送 carDto 2 MS 接收 CarDto 并转换为域。为此,我可以使用多种变体:

  1. 使用库例如mapstruct
@Mapper
public interface CarMapper {
    CarMapper INSTANCE = Mappers.getMapper(CarMapper.class );
    CarDto carToCarDto(CarDomain car);
}
Run Code Online (Sandbox Code Playgroud)

并使用:

CarDto carDto = CarMapper.INSTANCE.carToCarDto(carDomain);
Run Code Online (Sandbox Code Playgroud)
  1. 创建手动映射器:
class CarMapper {
        public static CarDto toDto(CarDomain car) {
            CarDto carDto = new CarDto();
            carDto.setName(car.getName());
            carDto.setYear(car.getYear());
            carDto.setColor(car.getColor());
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在我们使用 2 变体。因为当我们构建微服务并在models moduleDTO 模型更改的某些领域中时,我们会在编译时出错。例如,有人将这个 dto 模型改名为models module

private String name; 
Run Code Online (Sandbox Code Playgroud)

private String name1;
Run Code Online (Sandbox Code Playgroud)

当我们构建项目时,我们在这一行出现错误:

carDto.setName(car.getName());// getName not found becose now getName1
Run Code Online (Sandbox Code Playgroud)

但这条路很难。对于每个 dto/域模型,我们需要创建映射器并编写每个字段。在 1 变体中更容易,但如果 dto 更改,我们会在运行时出错。

告诉我如何匹配/映射模型 dto/domain 的最佳方法?

Voi*_*son 5

因为当我们构建微服务并在模型模块中更改 DTO 模型的某些领域时,我们会在编译时出错。

您面临的问题通常被认为是消息版本控制。

微服务的一个关键思想是它们可以相互独立地重新部署;您应该能够随时更改它们而不会破坏其他一切。为了实现这一点,我们将微服务之间的耦合限制为它们共有的消息。

因此;因此,使消息模式“正确”非常重要

用鼠标右键在这种情况下,并不意味着你找出正确的信息发送的第一次,但不是你投资在了解如何改变的消息前期设计之都,什么消息结构支持这些变化。

我所知道的关于该主题的最佳参考资料是 Greg Young 的书Versioning in an Event Sourced System

Greg 提出了使用“弱模式”来支持向前和向后兼容性的案例;基本思想是

  • 字段的含义永远不会改变
  • 消费者必须忽略并且必须转发它不理解的字段
  • 大多数(全部?)字段应该是可选的;消费者必须为消息中缺少某些数据元素的事件做好准备。这可能意味着准备一个可接受的默认值,或替代处理。

牢记基础;您可以查看AvroThriftProtocol Buffers的详细信息,以了解标准化格式的发展趋势。Martin Kleppmann在 Avro、Protocol Buffers 和 Thrift 中Schema Evolution的讨论可能是一个很好的中间步骤。

消息纪律非常重要——模式是微服务 API 的一部分。向 API 引入向后不兼容的更改会带来很多风险,不应掉以轻心。

我有包含所有 DTO 类的模型模块。

那可能是一个错误;很难说。拥有一个经常以不向后兼容的方式发展的公共核心当然是错误的。这种习惯应该改变。