gpt4 book ai didi

c# - 如何在微服务之间共享领域事件方案?

转载 作者:行者123 更新时间:2023-12-05 03:55:41 24 4
gpt4 key购买 nike

在领域驱动设计中,我们创建了有界上下文。这意味着聚合不共享通用模型。

这张来自 Microsoft 的图片显示了聚合如何使用命令和事件进行通信 (source)。 Communication between aggregates

假设这些聚合至少是在不同存储库中编码的两个不同微服务。 他们应该如何共享与其通信的命令和事件的方案定义?在我的例子中,这些应用程序是 .net 核心应用程序,因此与 .net 兼容的序列化和反序列化将不胜感激。

此外,也许我遗漏了一些要点,因为我是领域事件的新手,并且通信工作方式不同,那么我想知道,我没有看到什么。

最佳答案

每个服务都可以有一个内部模型,您可以使用 Canonical Data Model用于服务之间的通信。

通常有一个单独的模型用于集成服务使用的内部模型。

您还可以检查 enterpriseintegrationpatterns.com 中的所有模式并拿到书。强烈推荐。

编辑:

这是一个订单系统的例子。我将跳过对象必须的一些数据以简化示例,并尝试专注于重要部分,即 CDM 和内部模型。

注意 举一个简单的例子,总是很难证明某些决定的合理性,因为大多数事情都会随着额外的东西变得更简单。以这种方式完成实现以帮助示例。

在我继续之前:拥有 CDN 会产生一些从内部模型到外部模型的转换开销。如果你认为你可以没有它,那就去做吧。不要让事情变得比他们需要的更复杂。这里的问题是,如果您需要更改命令或事件,这将传播到所有服务,并会在您的系统中引起巨大的链式 react 。 Domain-Driven Design 书中有一节是关于 Anti-Corruption Layer 的。请检查一下。

我们为什么要使用 CDM?对于 Encapsulation .与对象封装其数据的方式相同,服务封装其内部结构。 CDM 旨在仅用于服务之间的通信/集成,并旨在在它们之间共享。

与其他服务共享服务的内部模型是一件坏事,因为它会阻止开发人员更改此内部模型。此外,有时一项服务的详细信息可能会泄漏到其他服务,并可能导致严重问题。

共享一个专为服务之间的通信设计的特殊数据模型是一件好事,因为它为通信强制执行了一个定义良好的模型,并且您的系统不会变成一堆事件和命令具有未知的模式,其中每个 Service 发布和消费它喜欢的任何东西。我见过那种恐怖,相信我,你不会想要的!

这个模型应该在更高的抽象层次上设计:系统层次,考虑它的过程和流程。它应该没有关于各个服务内部的任何细节。

你需要的是Translation内部模型和外部模型之间。此外,您可以使用 ContentFilterContentEnricher如果您需要过滤传入事件或命令并向传出事件或命令添加更多数据。

// Canonical Data Model

namespace CDM {

public interface ICommand { }
public interface IEvent { }

public class CustomerInfo {

public Guid Id { get; set; }
// notice here the CDM uses the two separate properties for the first and last name
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class LineItemData {

public Guid ProductId { get; set; }
public Quantity Quantity { get; set; }
public Money ListPrice { get; set; }
}

public class PlaceOrderCommand : ICommand {

public CustomerInfo CustomerInfo { get; set; }
public IReadOnlyList<LineItemData> LineItems { get; set; }
}

public class OrderPlacedEvent : IEvent {

public Guid OrderId { get; set; }
public IReadOnlyList<LineItemData> LineItems { get; set; }
}

} // end Canonical Data Model namespace

// Order Service Internals

// the name is done this way to differentiate between the CDM
// and the internal command, do not use it this way into production

public class LineItem {

// the internal one includes the OrderId { get; set; }
public Guid OrderId { get; set; }
public Guid ProductId { get; set; }
public Quantity Quantity { get; set; }
public Money ListPrice { get; set; }
}

public class PlaceOrderInternalCommand {

public Guid CustomerId { get; set; }
public string CustomerFullName { get; set; } // a single full name here
public IReadOnlyList<LineItemData> LineItems { get; set; }
}

public class Event { }

public class OrderPlacedInternalEvent : Event {

public Guid OrderId { get; set; }
public IReadOnlyList<LineItem> { get; set; }
}

// this is part of the infrastructure, received messages and translates/transforms
//them from the external CDM to the internal model.
// This is the input/receiving part of the service

public class CommandDispatcher {

public void Dispatch(ICommand cmd) {

// here we will use a MessageTranslator, check PatternsUsed section

var translator = TranlatorsRegistry.GetFor(cmd);
var internalCommand = translator.Translate(cmd);
Dispatch(internalCommand);
}
}

public class CommandHandler {

public void Handle(PlaceOrderInternlCommand cmd) {

// this will create the OrderCreated event
var order = CreateOrder(cmd);
// this will save the OrderCreated event
OrderRepository.Save(order);
}
}

// Another part of the infrastructure that publishes events.
// This is the output/sending part of the service

public class EventPublisher {

public void Publish(Event event) {

// another usage of the MessageTranslator pattern, this time on events
var translator = EventTranslatorRegisty.GetFor(event);
var cdmEvent = translator.Translate(event);
// publish to kafka or whatever you are using
PubilshToMessageMiddleware(cdmEvent);
}
}

使用的模式:

Canonical Data Model MessageTranslator CommandMessage EventMessage

关于c# - 如何在微服务之间共享领域事件方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60018336/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com