在我们的环境中,为了确保容灾,我们将在另一个城市部署另一台服务器。如下图所示:
Node2是我们要部署的服务器。业务要求是,当接受付款时,应向用户发送电子邮件,并在系统中生成发票。但是,部署了另一个节点,所有四个订户都将收到该事件,这意味着用户将收到两封电子邮件,并将生成两张发票。
一个解决方案是,在订阅者中,我们实施了一个idempontent算法,以防止发布第二个电子邮件/发票。有性能损失。在每个正常情况下,两个Emain Notification订阅者都会收到一个事件,我感觉不是很正确。一个理想的情况是,活动只会收到两个电子邮件通知订阅者中的一个和两个发票生成订阅者中的一个。
我知道即使我们没有复制的服务器,我们仍然需要idempontent行为。但是,只有在多次收到事件时才会使用它。
是的,我们正在使用ActiveMQ。答案 0 :(得分:1)
您应该只使用队列将事件发布到。只有一个节点能够抓取单个事件并处理电子邮件。我怀疑你今天要发表一个主题,因为每个订阅者都会收到一份副本。
这假设您在其他地方每次付款只生成一个事件。
阅读本文 http://activemq.apache.org/how-does-a-queue-compare-to-a-topic.html
要将消息分成两部分,有很多方法。一个快速的解决方案是在ActiveMQ中配置virtual destinations。
复合队列会将邮件复制到多个位置:
<compositeQueue name="EVENT.PAY">
<forwardTo>
<queue physicalName="SEND.EMAIL" />
<queue physicalName="GENERATE.INVOICE" />
</forwardTo>
</compositeQueue>
VirtualTopics也可以解决您的情况(与上面链接的相同文档)。
您可以将您的活动发布到(虚拟)主题,例如VirtualTopic.Event.Pay
。
然后让您的电子邮件消费者从排队 Consumer.Email.VirtualTopic.Event.Pay
读取,并从排队 Consumer.Invoice.VirtualTopic.Event.Pay
读取发票消费者。
如文档中所示,可以重新配置虚拟主题的默认命名约定。