Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relationship between JMS connections, sessions, and producers/consumers

Tags:

java

jms

I want to send a batch of 20k JMS messages to a same queue. I'm splitting the task up using 10 threads, so each will be processing 2k messages. I don't need transactions.

I was wondering if having one connection, one session, and 10 producers is the recommended way to go or not?

How about if I had one producer shared by all the threads? Would my messages be corrupt or would it be sent out synchronized (giving no performance gain)?

What's the general guideline of deciding whether to create a new connection or session if I'm always connecting to the same queue?

Thank you and sorry for asking a lot at once.

(Here's a similar question, but it didn't quite answer what I was looking for. Long lived JMS sessions. Is Keeping JMS connections / JMS sessions allways open a bad pratice? )

like image 810
Russell Avatar asked Jan 19 '11 22:01

Russell


People also ask

What is producer and Consumer in JMS?

A JMSProducer is created by a JMSContext and is used to send messages to a queue or topic. The JMSProducer object causes the creation of objects that are required to send the message. JMSConsumer. A JMSConsumer is created by a JMSContext and is used to receive messages from a topic or a queue.

Can JMS queue have multiple producers?

Yes, we can have multiple producers for single queue. Multiple producers can also publish messages at the same time.

What is a JMS session?

A session is a single-threaded context for producing and consuming messages. You use sessions to create the following: Message producers. Message consumers.

How do I get JMS session?

To create a session, a JMS application uses the createSession() method of a Connection object. The createSession() method has two parameters: A parameter that specifies whether the session is transacted or not transacted. A parameter that specifies the acknowledgment mode for the session.


1 Answers

Is it OK if some of the messages are duplicated or lost? When the JMS client connects to the JMS broker over the network there are three phases to any API call.

  1. The API call, including any message data, is transmitted over the wire to the broker.
  2. The API call is executed by the broker.
  3. The result code and any message data is transmitted back to the client.

Consider the producer for a minute. If the connection is broken in the first step then the broker never got the message and the app would need to send it again. If the connection is broken in the third step then the message has been successfully sent and sending it again would produce a duplicate message. The app cannot tell the difference between these and so the only safe choice is to resend the message on error. If the session is transacted the message can be safely resent in all cases because if the original had made it to the broker, it will be rolled back.

Consider the consumer. If the connection is lost in the third step then the message is deleted from the queue but never made it back to the client. But if the session is transacted the message will be redelivered when the application reconnects.

Outside of transactions there is the possibility of lost or duplicate messages. Inside of a transaction the same window of ambiguity exists but it is on the COMMIT call rather then the PUT or GET. With transacted sessions it is possible to send or receive a message twice but not to lose one.

The JMS spec recognizes this window of ambiguity and provides the following guidance:

If a failure occurs between the time a client commits its work on a Session and the commit method returns, the client cannot determine if the transaction was committed or rolled back. The same ambiguity exists when a failure occurs between the non-transactional send of a PERSISTENT message and the return from the sending method.

It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages.

A message that is redelivered due to session recovery is not considered a duplicate message.

JMS sessions should always be transacted except for cases where it really is OK to lose messages. If the sessions are transacted then you'd need session and connection per-thread due to the JMS thread model.

Any advice about performance impacts would be vendor-specific but in general persistent messages outside of syncpoint are hardened to disk before the API call returns. But a transacted call can return before the persistent message is written to disk so long as the message is persisted before the COMMIT returns. If the vendor optimizes based on this, then it is much more performant to write several messages to disk and then commit them in batches. This allows the broker to optimize writes and disk flushes by disk block rather than per-message. The number of messages to put in the transaction decreases with the size of the message and beyond a certain message size dwindles back down to one.

If your 20k messages are relatively small (measured in k and not mb) then you probably want to use transacted sessions per thread and tune the commit interval.

like image 184
T.Rob Avatar answered Sep 19 '22 06:09

T.Rob