We can learn something here by looking at what's done by current strong MOM/JMS software. MQSeries for instance has queue managers that are essentially JMS servers or the implementation of one. They also have a concept of MQ clusters where two or more queue managers can join in a cluster. At least one or preferrably two queue managers in a cluster are called "Repository" queue managers and they have channels (connections) to all other queue managers. These channels are necessory because repository queue managers have to keep what queues/topics are defined on what queue managers.
If a queue is shared in cluster, that means that a client can connect to any server in that cluster and send a message to that queue and it will get to that queue via channels (connections) to the repository queue managers. You can also have the same queue defined on two different queue manager servers and share them both in the queue. In that way when a message is sent to that queue, by default it is round robined, first goes to one instance and the second message will then go to the second instance and hence load balancing is achieved.
Failover is a completely different problem. No-durable messages can be lost. They are non-persistent afterall for a reason. Persistent or durable messages have to be moved over to an alternate server. They only way of doing this without using native clustering facilities like Windows Advanced server with a shared disk array is to keep messages at a shared point like in a database where even if the OS goes down of one JMS server, the other JMS servers can access those messages from the central message store and take over. This however, makes things quite slow. Software like MQSeries provides failover with native support like Windows Advanced server clustering support or other clustering support. I would leave failover as a secondary objective and concentrate on speed and scalability first.
This comment was posted by Bill Burke on jboss-group mailing list. I'm reposting it here to facilitate discussion.
> Sounds like the duty of client interceptors.
IMHO, its the duty of the server. The server should replicate the subscribers across the cluster. What I mean by this is that the server replicates the client proxies of the subscribers across the cluster (replicated RMI proxies for instance).
> Frankly, I'm struggling to apply the dynamic client proxies to JMS
> since the JMS API is static in nature. I fail to see how proxy
> creation is necessary at all. Can someone explain this to me?
> Additionally, I'm getting confused
> with the mixed use of the terminology of "aspect" and
> "interceptor." Do you
> consider these terms interchangeable?
Proxy is important because you can attach interceptor behavior to your clients and re-use the Invoker MBean architecture. For instance, you could re-use the client Tx and Security interceptors to automagically propagate transactional and security information across the wire. ISVs can add proprietary APIs (attaching interfaces via new interceptors) to JMS. Also, encapsulating Transactional and Security propagation in one interceptor object helps with maintainability as this integration/code changes. Proxies give us power and flexibility and managability and reusability even with a static api.
The way I see it is, Topics and Queues are MBeans and receive everything through a generic MBean invocation. If you do it this way, communication is unified/generalized across EJB, MBeans, and JMS and you can leverage existing code.
BTW, interceptor is a subset of aspect. Aspects have interceptors but also the ability to attach additional interfaces to the object. Go to the aspect forum to get more information.
> Yes, I prefer this architecture to the master/slave relationship that
> many organizations implement for clustering and failover. Any node
> in a cluster should be able to take over for any other node in a
Yes, this is the way EJBs and the Web tier are working.
This forum is for technical questions not architectural questions.
If you want somebody to design your app, hire a consultant.
- What if a component is processing the request (doing some stuff with it in a TX and then repost on TX commit) and, AT THE SAME TIME, a SB whant to remove it because the request should be canceled (Will the SB waits the commit because the message is in a transaction?)
The SB can only remove the message if it is in the queue. If somebody has
already received it (regardless of whether the receipt is acknowledged/committed)
the SB will not find it and will not wait.
- About performence, fetching the message based on a JMS header (so selector) is heavy. Is there an optimized way to fetch the message (knowing that the selector is a primary key sort of).
This is not optimized in JBossMQ, it is in other JMS providers.
It is a good idea - I will add it to my TODO list.
Other JMS providers will also let you provide a "preferred index/message selector"
and will then optimize internally for that pattern.
"This forum is for technical questions not architectural questions.
If you want somebody to design your app, hire a consultant. "
I described only my architecture to help people understand the problem. I think my questions are technichal, right?
I only got as far as "I have some questions about this architectural choice"
before skipping over to the real questions.
I would like to contribute. Let me know if I can help in any way (I don't know yet the JBossMQ codebase yet).