JMS performance

Lukas Eder picture Lukas Eder · Mar 29, 2011 · Viewed 8.8k times · Source

I'm having a bit of trouble with understanding JMS from a performance perspective. We have this very straightforward code in our application:

QueueConnection connection = null;
QueueSession session = null;
QueueSender sender = null;
TextMessage msg = null;

try {
  // The JNDIHelper uses InitialContext to look up things
  QueueConnectionFactory qcf = JNDIHelper.lookupFactory();
  Queue destQueue = JNDIHelper.lookupQueue();

  // These objects are created for every message, which is quite slow
  connection = qcf.createQueueConnection();
  session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  sender = session.createSender(destQueue);

  // This is the actual message
  msg = session.createTextMessage(xmlMsg);
  sender.setTimeToLive(0);
  sender.send(msg);
} 
finally {

  // Close all objects again
  JMSUtilities.safeClose(sender);
  JMSUtilities.safeClose(session);
  JMSUtilities.safeClose(connection);
}

The code is correct, but probably some of the above artefacts could be reused for several messages. These are our configurations:

  • We use Oracle Weblogic 10.3.3
  • Weblogic connects to IBM MQ 7.0 (Problem also appears with 6.0) for JMS
  • The above logic is executed by a single thread on a backend server. It would be simple to keep some objects (QueueConnection, QueueSession, QueueSender) in memory as there is no concurrency involved.

My questions

  • Which types of objects can be shared among several messages? (of course we'd include error recovery, restoring those shared objects)
  • What are best practices to improve performance?

Answer

SpaceTrucker picture SpaceTrucker · Sep 5, 2013

Here are some relevant parts of the jms spec:

section 2.8 Multithreading

JMS Object          Supports Concurrent Use
Destination         YES
ConnectionFactory   YES
Connection          YES
Session             NO
MessageProducer     NO
MessageConsumer     NO

section 4.4.14 Serial Execution of Client Code

JMS does not cause concurrent execution of client code unless a client explicitly requests it. One way this is done is to define that a session serializes all asynchronous delivery of messages

So as already mentioned reuse as much as possible. Reuse the ConnectionFactory, Connection and Destinations for all Threads. For each Thread reuse consumers and producers.

If you are reusing a JMS connection beware, that the JMS Provider will multiplex different sessions on that connections. So even if it is safe to reuse connections it might be faster to create a connection for every session you need.