在某些方面,您的问题可以改写为“如何在 SOA 环境中实施参照完整性”。那么答案是你不能。这是 SOA 原则中自治的一种副产品。
所以几乎按照定义,Employee 服务中的 Job Position 与 Job Position 服务中的 Job Position 不同。这实际上是一件好事。尽管这两种服务都定义了工作职位,但它们是从两种不同的能力来实现的,并且可以根据需要自由地开发和发展他们的能力。
因此,基于另一个服务边界内类似数据的存在来对删除一个服务边界内的数据进行硬限制是不可能的(甚至是不可取的)。
这一切都很好,但是您如何避免员工可能“匹配”到通过删除或更新以某种方式发生变化的工作职位的情况?
好吧,服务可能会对其他服务的更改感兴趣。在这些情况下,服务可以成为彼此的消费者。很明显,Employee 能力会对 Job Position 能力的变化感兴趣。
对于这种情况,事件实际上是一种使用得相当好的设计模式。如果业务操作导致服务数据发生更改,则该服务可以发布描述更改的事件消息。其他服务可以成为此类事件的消费者,并且可以以自己的方式处理它。因为事件通常是用发布-订阅语义实现的,所以任何需要的服务能力都可以订阅事件。
在您的示例中,如果职位被删除,可以发布的事件可以定义为(使用 C#):
class JobPositionRemoved
{
int JobPositionId { get; set; }
string JobPositionName { get; set; }
...
}
这个事件的消费者如何实际处理它(消费者将采取什么行动)是另一个问题,并且取决于消费者的能力。例如,您的员工服务可以收集具有此职位的员工列表并将其标记以供审查,或将其添加到“职位重新分配”队列中。
您的事件甚至可以包含一个名为的字段,该字段int ReplacedByJobPosition
使消费者能够自动更新依赖于已删除工作职位的任何功能。
只要您的事件是通过容错传输(例如消息队列)传递的,您就可以相当确信,虽然您的服务能力之间没有参照完整性,但您的整个系统最终应该会变得一致。
通过以这种方式使用事件,您还避免了对相互依赖关系的集中注册的需要(这听起来像是一个讨厌的想法)。每个服务负责发布有关对其自身数据的更改的事件,并且依赖关系由服务相互消耗事件来定义。
希望这会有所帮助。
编辑
在回答您的评论时 - 虽然我可以看到让另一个服务来处理该职位的好处:重新分配问题并且我认为这没有任何大问题,但有一些考虑因素。
服务边界和业务能力边界自然契合的原因之一是,当您更改业务能力(例如更改计费程序)时,它通常不会影响其他业务能力(CRM/财务/等)。通过引入共享服务,您将与多个功能耦合,您的服务没有明确定义的边界,因此需要进行大量更改,因此拥有成本更高。
此外,您可以争辩说,业务事件的消费者(例如,JobPositionRemoved)应该负责该事件的整个处理。
事件的处理很可能会触发要发布的后续事件(例如 ReviewTaskCreatedForEmployeeChange),如果需要,该事件随后可以由另一个消费者(例如工作流工具)处理。