Michael J
Michael J

Reputation: 21

JmsTemplate Invocation Latency in High Concurrency

We are currently doing Load Test with over 200 TPS to simulate high concurrency with the application using Spring Boot 2.1.1 and Spring JMS with IBM MQ Spring Boot Starter v2.1.1. Also, we configured MQ connection pool to have 500 max connection size with 60 seconds idle timeout.

ibm.mq.pool.enabled=true
ibm.mq.pool.idleTimeout=60
ibm.mq.pool.maxConnections=500

The problem is that there is a long waiting time (over 1 minutes) before sending a message to MQ when the load test reached to 100TPS and there is no clue where is a bottleneck. The only suspicious points are:

  1. Invoking MQ Client component (spring component) wrapping JmsTemplate
  2. Invoking JmsTemplate to send a message

From our dynatrace, it does not explain which one was slow; however, actual sending time was really fast. So, we suspected that it could be a problem with any of following:

1) JmsTemplate is a singleton and it might be a bottleneck 2) MQClient.class might be a bottle for the same reason as a singleton 3) MQ connection pooling is not working properly

We have tried to pin point through many ways like logging and tracing with Dynatrace during the performance test. But we have not found a root cause yet why it took so long before sending a message to MQ

@Component
@AllArgsConstructor
@Slf4j
public class MQClient {
    private final JmsTemplate jmsTemplate;
    private final QueueResolver queueResolver;
    public String requestSomething(
        final String someId,
        final String messageText) throws JMSException {
    final AtomicReference<Message> message = new AtomicReference<Message>();
    jmsTemplate.send(
            queueResolver.getRequestQueueName(someId),
            new MessageCreator() {
                @Override
                public Message createMessage(Session session) throws JMSException {
                    final BytesMessage msg = session.createBytesMessage();
                    msg.writeBytes(messageText.getBytes(Charset.forName("UTF-8")));
                    msg.setJMSReplyTo(session.createQueue(
                            queueResolver.getReplyQueueName(someId)));
                    message.set(msg);
                    return message.get();
                }
            });
    return message.get().getJMSMessageID();
    }
}

There was no error since it was long waiting time before sending out the MQ message.

Upvotes: 1

Views: 840

Answers (1)

Devrim
Devrim

Reputation: 15533

MQ connection pooling is not working properly

Your idle timeout value is 60 ms. Default is 30000 ms (30 seconds). This is the maximum time in ms that a connection can remain idle in the pool. So with your idle timeout property, connections are removed after 60 ms idle time and created when required. And creating a connection is time-consuming.

Try this:

ibm.mq.pool.idleTimeout=60000

Upvotes: 1

Related Questions