I have 3 apps. 1 app publishes an event to a RabbitMQ exchange which puts the event into a queue. I want both of my other apps to respond to the event, but instead they take turns. I’m guessing that this is due to some sort of round-robin…thing. What would be the proper way to handle this? Do I route the message to more than one queue?
The core assumption behind a message queue is that each message is handled by exactly one worker, so the behavior you’re seeing is as expected. For distribution of events, you would generally need to set up pub/sub instead of just a simple queue. This is better than making the event publisher publish to multiple queues, because that approach would put the burden on the publisher to know which consumers there are, which shouldn’t be the case.
RabbitMQ has a tutorial to do that here: https://www.rabbitmq.com/tutorials/tutorial-three-spring-amqp.html
We are aware that it’s not always easy to get routing of commands, events and queries right in a distributed Axon Framework application. We’re currently developing a new product called AxonHub designed to make this extremely easy. We’ll probably start private beta testing of this next week - let me know if you’re interested.
Testing… My previous messages were deleted for some reason.
Thanks for the quick response. For some reason, it seems that if I try to reply to your reply, then my message just gets deleted. Anyhow, thanks for the quick response. I’m new to RabbitMQ/AMQP/Messaging in general, so I figured that was by design. I get the basics, but need to learn which pattern(s) to use based on the use-case. Generally speaking, and not that I think I have a reason for doing so, but is it unusual to setup an Axon app to publish to more than 1 exchange? I’m using Spring Boot and, based on the config options available, it seems that I can only point to 1 exchange. I wrote my initial code based on Allard’s Complaints webinar. In that example, he configures the exchange/queue/binding on the producer side and then configures the listener on the consumer side. Again, generally speaking, is that normal or unusual in a production-grade app? Based on that tutorial, it seems like you configure the exchange on the producer side, and then configure the queue/binding on the consumer side. Lastly, I’m not opposed to beta testing, but I’m not sure how useful I would be since I’m still in the early stages of this Axon stuff.
Perhaps my experience may help you understand how you can work with AMQP in Axon to distribute events.
The main application I work on is the producer. It generates a lot of events; effectively a short burst of them on each import of data and a stream of them during use. The two sets of events each have a distinct parent package.
Various services and third party applications are interested in some of those events and subscribe to them. Some use Axon too, some don’t. Some are deployed as single instance, some have multiple instances.
The setup in use is one Fan Out Exchange to which the producer writes. Each subscriber has its own private queue. Because of the type of exchange, all queues get all the messages. The subscribers pick up the messages at their own pace. The subscribers using Axon work without trouble,. The ones not using Axon had to do something to be able to ignore unknown event messages.
If you want to do some routing you may want to look into using a Topic Exchange instead of a Fan Out. Then you can actually use routing keys when binding your queues (technically you can do that with the fan out too, but then those routing keys are ignored). The default routing key is the package name.
For production purposes you probably want to set up a rabbit mq cluster (2 nodes is sufficient for most cases, especially if you also have an event store you can replay in case of emergencies).
Another tip would be to have a so called dead-letter queue related to each queue and set up some monitoring that triggers whenever a message comes into the dead-letter queue.
So if all you want is all your subscribers processing each message, then I would say a single exchange should be enough.
Thanks for that narrative. That’s what I’m looking for. So far, what I’ve done is create 1 fanout exchange. Then, each app creates their own queue which is then bound to the exchange. This way, they all get their own copy of the message. But if there’s more than 1 instance of any given app, then it would get processed only once. When I used the word “route”, I meant it in a very general sense. I must say, this is all pretty neat stuff and I can’t wait to really put it to work.