Queue declaration on all nodes in RabbitMQ - rabbitmq

I have a Rabbitmq cluster setup (without HA). My consumers are spring applications and it provides a failover mechanism out of the box where it connects to the next available node.
Since the queues are not mirrored, is it okay if I declare the queues up front and when the first node goes down, the connection will be established to the second node. Does this make sense?
Another question, lets say I have a load balance on top of Rabbitmq cluster. My applications connect using the load balance. Will the queues be declared on all nodes or will it be declared on the node based on the routing strategy by LB.

For the first scenario, yes, the queues will be declared on the failover broker instance when the connection is established.
If you want to pre-declare on all nodes you will need a connection factory for each node, and a RabbitAdmin for each connection factory.
You will also need something to cause a connection to be opened on each (the RabbitAdmins register themselves as connection listeners).
You can do that by adding a bean the implements SmartLifecycle and call createConnection() on each connection factory.
You can also selectively declare elements. See Conditional Declaration.
By default, all queues, exchanges, and bindings are declared by all RabbitAdmin instances (that have auto-startup="true") in the application context.
Starting with the 1.2 release, it is possible to conditionally declare these elements. This is particularly useful when an application connects to multiple brokers and needs to specify with which broker(s) a particular element should be declared.

Related

Producer and Consumer not decoupled

From my reading around rabbitmq and AMQP, most exchanges, queues and bindings are done by the application e.g.
App1(Producer) declares exchange1
App2(Consumer) declares queue1 and binds to exchange1
I have seen then in order not to have missing messages that both should declare additional config, so now would be:
App1(Producer) declares exchange1, declares queue1 and binds to exchange1
App2(Consumer) declares exchange1, declares queue1 and binds to exchange1
Now the Producer App needs to know details it never needed to known.
Is this acceptable? It feels wrong
For the cosumer to be able to bind an exchange to a queue he wants to consume messages from, the exchange must exist and have the expected type (fanout, direct, topic) and configuration.
Consider a situation where the consumer would rely on the exchange being created by somebody else. If he would just create the queue and then try to bind it to the missing exchange, he would get an error.
In a scenario where specificicly configured things (exchange, queue, binding) must exist before a consumer can do his part of the setup, you have three options:
Configure the required things by a third party that is guaranteed to finish before producers and consumers run from application code.
Configure the required things by the producer or the consumer and make sure this part of the application code is run first.
Let the producer and the consumer perform identical steps to configure the required things. This makes the order in which the different parts of the application code are executed irrelevant.
The third option works if the configuration steps are identical in all aspects. For example, RabbitMQ accepts the repeated creation of an exchange, if this configuration always is identical. It throws an error, if an existing exchange is configured again with differing configuration.
I would say the the third option is advisiable for a scenario where the application code does the setup. It feels right to me.

Using two instances of Bus and handling events from both the instances

In our ecosystem we want to use two Rabbit brokers for NSericeBus transport.
I observed with a spike, that I am able to get messages from both the brokers by instantiating two bus instances (on worker). No other change was required for the handlers.
If this approach is ok for integration scenarios (with other systems) in case other systems are using a different Rabbit Broker? Or in case if we want to use a additional Rabbit broker for failover (with some custom code to switch the publish/send to the available node)?

JMS message received at only one server

I'm having a problem with a JEE6 application running in a clustered environment using WebSphere ApplicationServer 8.
A search index is used for quick search in the UI (using Lucene), which must be re-indexed after new data arrived in the corresponding DB layer. To achieve this we're sending a JMS message to the application, then the search index will be refreshed.
The problem is, that the messages only arrives at one of the cluster members. So only there the search index is up to date. At the other servers it remains outdated.
How can I achieve that the search index gets updated at all cluster members?
Can I receive the message somehow on all servers?
Or is there a better way to do this?
I found a possible solution:
Generally, a JMS message delivered via a queue goes only to one of the cluster members. I found a possible way to get the info to all of the cluster members, using a EJB timer. Creating a non-persistent timer should call the callback method on all of the cluster members. This might be a convenient way to recreate the local search index on all the cluster members.
It is important to be a non-persistent ejb timer, because persistent timers get synchronized on the cluster and are only executed on one of the cluster members.

RabbitMQ Per-Connection Queue Creation and Deletion

I've been adopting RabbitMQ in a new project. I'll need a clustered environment to support system failure and high-demand. On to the problem: queues must be created as exclusive whenever a client connects. If the client disconnects, I want the queue to be deleted, freeing its resources. Furthermore, queue binding to topics must be limited with per-credential permissions.
Concluding, I would like to constraint connection to create only exclusive queues (that would auto-delete when the connection closes) and only bind such queue to a list of topics I would allow, configured per user account.
I'm not being able to either limit queue creation to exclusive, nor limit the topics a client can subscribe to. I could impose this constraint based on VHOSTS, but that would require the dynamic creation of VHOSTS and probably hundreds of them.
Is this possible in RabbitMQ? Is there a better approach to it?
Thanks
If you only want clients to be able to create exclusive queues you may need to write your own wrapper and abstract away RabbitMQ from the clients completely. Have your clients talk to RabbitMQ through this wrapper and deal with queue creation and binding here.
This would expose your own version of queue_declare which then calls the RabbitMQ queue_declare method setting exlusive=true.

RabbitMQ implementation of AMQP protocol

I have some problem so can you help me. Is instance of AmqpTemplate class from RabbitMQ ( implementation of AMQP protocol) thread safe. Can it be accessed from multiple threads?
Thanks
AmqpTemplate is the interface, and RabbitTemplate is the implementation, and I assume by "thread-safe" you mean that its send/receive/sendAndReceive methods may be used concurrently. If so, then YES. The only state it maintains within instance variables are "converter" strategies for the Message and MessageProperties as well as default Exchange, Queue, and Routing Key settings (which are not even used if you invoke the methods that take those as arguments instead), and all of those are typically configured one time initially (e.g. via dependency injection). The template does not maintain any non-local state for any particular operation at runtime. With AMQP, the "Channel" is the instance that can only be used by one thread at a time, and the RabbitTemplate manages that internally such that each operation is retrieving a Channel to use within the scope of that operation. Multiple concurrent operations therefore lead to multiple instances of Channel being used, but that is not something you need to be worried about as an end-user of the template.
Hope that helps.
-Mark