I want to build a broadcasting system. It consists of several groups. Each group has one User who can broadcast a message to the other members of the same group. What is the appropriate JMS architecture for this kind of system?
Should I use a topic with durable subscription? I don't know much about pub/sub messaging style, can topic have multiple subscription? If so, then each subscription represents a group in the broadcasting system. If not, should I use a queue whereas each message has a header specifying the group and then use a JMS selector to filter the message so that each member receive only messages from groups he's in?
Also, I am thinking of persisting the messages after consumption. I decided to make each message to expire after one hour, and each member should check the database for every message he misses. But, how can I fire an action upon message expiration?
Topics can be used... Topics can have multiple subscribers. Each group can use a different topic. The user can send message to that topic and all the subscribers would receive it.
The durable subscribers are required only if the subscribers can go offline for sometime and the messages for the subscriber shouldn't be lost.
Queue doesn't suite well in one-to-many scenarios. But if you have a pre-defined set of receivers you can use a queue for each one of them and route messages to that. But this is a overhead to route the messages to the receiver's queue. JMS selector idea you have suggested would work but for a queue only one client can receive a message. In topics it distributed to all the clients interested in that topic.
Normally one would persist data to database and not the message itself. So you can persist to database and then create the message for delivery.
Related
I've seen a lot of code and examples on how to send a message from the server/producer to the client, but I'm lost as to how to send a message from the client to the server. Does it follow the same format?
For example, say my server has 5 topics: A, B, C, D, E. My client is listening to only topic C.
So my server creates a queue and sends messages to subscribers/clients.
My client gets messages that are on topic C. It performs some computation, and I want to send a message back to the publisher (say an int for example). What are the required steps?
Do I need to set a destination/topic for the producer to listen to?
Does my producer automatically listen to all clients (once they connect)?
I think you may need to do a bit of reading around the various communication models available e.g. this on JMS Models.
You have started by using Topics, but your statements hint at a One-to-One relationship between sender and receiver. For this queues may be more appropriate. Topics are generally for publishing information where the publisher doesn't know (nor care) about the subscribers - and there can be many.
On the other hand Queuing is intended to deliver to a specific target. With this you can still do "fire-and-forget" (where the sender puts the message out to a queue and doesn't wait for the expected consumer to process it)
Or you can add response handling to that - essentially by adding a "parallel" response queue (where the initial sender will processes the response messages back from the consumer - usually in a different thread).
ActiveMQ and JMS have "reply-to" functionality - where the sender indicates on send the queue name where it wants to see responses come back to - and the consumer complies with that. The reply-to queue can be fixed or a temporary one that the sender creates up-front.
All depends on what model you are going for.
Using RabbitMQ, I have two types of consumers: FileConsumer writes messages to file and MailConsumer mails messages. There may be multiple consumers of each type, say three running MailConsumers and one FileConsumer instance.
How can I do this:
Each published message should be handled by exactly one FileConsumer instance and one MailConsumer instance
Publishing a message should be done once, not one time for each queue (if possible)
If there are no consumers connected, messages should be queued until consumed, not dropped
What type of exchange etc should I use to get this behavior? I'd really like to see some example/pseudo-code to make this clear.
This should be easy to do, but I couldn't figure it out from the docs. It seems the fanout example should work, but I'm confused with these "anonymous queues" which seems like it will lead to sending same message into each consumer.
If you create queue without auto-delete flag, then queues will stay alive even after consumers disconnection.
Note, that if you declare queue as persistent, it will be present even after broker restart.
If you will publish then messages with delivery-mode=2 property set (that mean that message will be persistent), such messages will stay in persistent (this is important to make queue persistent) queues even after broker restart.
Using fanout exchange type is not mandatory. You can also use topic for better message routing handling if you need that.
UPD: step-by-step way to get what you show with schema.
Declare persistent exchange, say main, as exchange.declare(exchange-name=main, type=fanout, durable=true).
Delcare two queues, say, files and mails as queue.declare(queue-name=files, durable=true) and queue.declare(queue-name=mails, durable=true)
Bind both queues to exchange as queue.bind(queue-name=files, exchange-name=main) and queue.bind(queue-name=mails, exchange-name=main).
At this point you can publish messages to main exchange (see note about delivery-mode above) and consume with any consumer number from queues, from files with FileConsumer and from mails with MailConsumer. Without any consumers on queues messages will be queued and stay in queue until they consumed (or broker restart is they are not persistent).
Are messages received on a Websphere MQ topic that you are subscribed to strictly ordered?
In other words, in similar fashion to a queue, given that your connection is maintained are you guaranteed to receive the topic messages in the same order as they were sent?
As per JMS specs
JMS defines that messages sent by a session to a destination must be received
in the order in which they were sent. This defines a partial ordering
constraint on a session’s input message stream.
JMS does not define order of message receipt across destinations or across
a destination’s messages sent from multiple sessions. This aspect of a
session’s input message stream order is timing-dependent. It is not under
application control.
Also
Although clients loosely view the messages they produce within a session
as forming a serial stream of sent messages, the total ordering of this stream
is not significant. The only ordering that is visible to receiving clients is
the order of messages a session sends to a particular destination.
Several things can affect this order like message priority,
persistent/non persistent etc.
So to answer your question it is not really JMS provider specific what order messages are received. They will be received in the same order they were sent with above information. The order in which messages are delivered to the server however will be constrained by limitations like message priority, persistent/non persistent etc.
How to create/preconfigure durable subscriber(s) in activemq.xml so that these subscriptions are ready upon ActiveMQ comes up? As if subscribers are in the offline state.
We're expecting a fixed (yet configurable) number of known subscribers.
Wanna buffer all msgs sent by the publisher starting day 1, in case not all subscribers
are up. Not sure if this is a common scenario but thanks in advance for the help.
This is a really common use case. What you should actually be looking at is composite destinations, rather than durable topics (there are loads of problems with this functionality, the main one being messages not being persisted by default and therefore not surviving broker outages).
Using this scheme you set up a composite topic to forward each message to a number of queues - a dedicated one per subscriber.
<destinationInterceptors>
<virtualDestinationInterceptor>
<virtualDestinations>
<compositeTopic name="orders">
<forwardTo>
<queue physicalName="orders.consumer1" />
<queue physicalName="orders.consumer2" />
</forwardTo>
</compositeTopic>
</virtualDestinations>
</virtualDestinationInterceptor>
</destinationInterceptors>
This way when your subscriber eventually connects to its own queue, it drains the messages that were fed into it.
A word of caution, make sure that your memory limits are large enough to deal with the messages stored in these queues, or your broker will appear to hang (a broker function called producer flow control).
I see that you are a new user, so if this answers your question, please tick it.
you could look into using a durable queue (as opposed to a topic) and use queue browsers (subscribers) to receive messages. The onus on tracking sequence numbers is then on the subscriber side (not sure if that is doable in your case). Queue browsers do not delete messages from the durable queue. You either have to use messages with a time to live or perhaps use a regular queue subscriber after certain time periods to flush out the old messages.
Queue browsers with durable queues are less taxing on the server - but you're pushing more load on the subscribers.
Hope it helps.
Say I load messages in a queue from multiple nodes.
Then, one or many nodes are pulling messages from the queue.
Is it possible (or is this normal usage?) that the queue guarantees to not hand out a message to more than one server/node?
And does that server/node have to tell the queue it has completed the operation and the queue and delete the message?
A message queuing system that did not guarantee to hand out a given message to just one recipient would not be worth the using. Some message queue systems have transactional controls. In that case, if a message is collected by one receiver as part of a transaction, but the receiver does not then commit the transaction (and the message queue can identify that the original recipient is no longer available), then it would be reissued. However, the message would not be made available to two processes concurrently.
What messaging/queuing technology are you using ? AMQP can certainly guarantee this behaviour (amongst many others, including pub/sub models)
If you want this in Java - then a JMS compliant messaging system will do what you want - and most messaging systems have a JMS client. You can Use Spring's JmsTemplate for real ease of use too.
With JMS - a message from a Queue will only be consumed by one and only one client - and once it is consumed (acknowledged) - it will be removed from the messaging system. Also when you publish a message using JMS - if its persistent - it will be sent synchronously, and the send() method won't return until the message is stored on the broker's disk - this is important - if you don't want to run the risk of loosing messages in the event of failure.