Devs love ZenUML
Devs love ZenUML

Reputation: 11892

How the Subscribers should be replicated when using message queue

In our environment, to ensure a disaster tolerance, we are going to deploy another server in a different city. As shown in the below diagram:enter image description here

Node2 is the server we are going to deploy. The business requirement is that when payment is accepted, an email should be sent to the user and an invoice should be generated in the system. However, another node is deployed, the event will be received by all four subscribers, which means the user will receive two email and two invoice will be generated.

One solution is that in the subscribers we implement an idempontent algorithm to prevent the second email/invoice to be issued. There is performance penalty. I don't feel it quite right when in every normal case an event will be received by two Emain Notification subscribers. An ideal case would be that the event will be received only one of the two Email Notification subscribers and one of the two Invoice Generation subscribers.

I understand that we need the idempontent behaviour anyway even we do not have a replicated server. But that would be used only in rare cases when an event is received more than once.

Btw, we are using ActiveMQ.

Upvotes: 0

Views: 85

Answers (1)

Petter Nordlander
Petter Nordlander

Reputation: 22279

You should simply use a queue to publish your event to. Only one of the nodes will be able to grab a single event and process the email. I suspect you are publishing to a topic today, since you get a copy per subscriber.

This assumes you only produce one event per payment elsewhere.

Read this http://activemq.apache.org/how-does-a-queue-compare-to-a-topic.html

To split a message in two, there are many ways. One quick solution is to configure a virtual destinations in ActiveMQ.

1

A composite queue will copy a message into several places:

<compositeQueue name="EVENT.PAY">
   <forwardTo>
      <queue physicalName="SEND.EMAIL" />
      <queue physicalName="GENERATE.INVOICE" />
   </forwardTo>
</compositeQueue>

2

VirtualTopics would also solve your situation (same documentation linked to above). You can have your events published to a (Virtual) topic, say VirtualTopic.Event.Pay.

Then have your Email consumers read from queue Consumer.Email.VirtualTopic.Event.Pay and invoice consumer read from queue Consumer.Invoice.VirtualTopic.Event.Pay.

  • No further logic is needed, since AMQ handles this by naming convention.

As found in the documentation, the default naming convention for Virtual topics can be reconfigured.

Upvotes: 1

Related Questions