Search code examples
multithreadingjmeterperformance-testingibm-mq

How to handle multiple MQ connections and sessions management inside JMeter?


Starting with the help provided by the information from this article, I have implemented an IBM MQ Point-to-Point testing solution using JMeter with JSR223 Samplers, Interthread Communication Plugin to pass information between consumer and producer threads and the help of some awesome people in the stack overflow community. The main feature besides what the article above shows is that this solution synchronizes threads made by the Producer thread group with threads from the Consumer Thread group in order to calculate how long a specific message took to be put from one request queue to another response queue. In this solution I only use one connection and session for the "Request Producing" Threads inside a Producer thread group and one other connection and session for the "Request Consuming" Threads. These connections and sessions are created at the beginning.

The producer setUp Thread group which executes only once at the beginning of the test, ends with these lines which create these 3 objects which I can grab in the Producer Thread group and use them to Produce one or more messages and send to one input queue:

System.getProperties().put("SessionInbound", sessInboundQueue)
System.getProperties().put("ConnectionInbound", connInboundQueue)
System.getProperties().put("DestinationInbound", destinationInboundQueue)

Similarly, the "consumer setUp Thread group" which executes only once at the beginning of the test, ends with these lines which create these 3 objects which I can grab in the Consumer Thread group and use them to Consume one or more specific messages from the output queue:

System.getProperties().put("SessionOutbound", sessOutboundQueue)
System.getProperties().put("ConnectionOutbound", connOutboundQueue)
System.getProperties().put("DestinationOutbound", destinationOutboundQueue)

Then, in the Producer I essentially do this:

def sessInboundQueue = System.getProperties().get("SessionInbound")
def destinationInboundQueue = System.getProperties().get("DestinationInbound")

producer = sessInboundQueue.createProducer(destinationInboundQueue)
...
producer.close()

And, in the Consumer I essentially do this:

def sess = System.getProperties().get("SessionOutbound")
def destination = System.getProperties().get("DestinationOutbound")

consumer = sess.createConsumer(destination, "JMSCorrelationID='" + inboundMessageId + "'" )
....
consumer.close()

And at the very end of the test I have 2 tearDown Thread Groups: one for the InboundQueue connection created initially in the setUp Thread Group and one for the OutboundQueue connection:

System.getProperties().get("SessionInbound").close()
System.getProperties().get("ConnectionInbound").close()



System.getProperties().get("SessionOutbound").close()
System.getProperties().get("ConnectionOutbound").close()

So, I used essentially one single connection and session object through which to send all the threads which Put many messages per second on input queue1 and one single connection and session object through which I Get many targeted messages from output queue1.

Now, the problem is that I should also test the system's capacity to handle multiple concurrent requests coming via multiple connections at the same time.

I think using just one connection can be a bottleneck, but also creating a connection for each thread is too much.

I need something like this table I made below. Currently I only handle the first line, except that all requesters use the same connection (a requester being just some string value in the payload).

enter image description here

My thought is that I should define different connection details and wrap them up under a producer1-N and a consumer1-N and based on each Requester1-N string (which comes differently for each thread from a CSV file), to use the needed producer1-N and consumer1-N (which sends/consumes to/from queue 1-N) based on the above excel mapping.

  • How can this above-explained situation be managed in the easiest way in JMeter?
  • Does anyone see a better approach to the problem?

I would greatly appreciate any advice.


Solution

  • Your JMeter test must represent real-life system usage as close as possible so you need to open as many connections as the upstream system will open and send the same amount of messages of the same size as it will be in reality.

    I have no idea regarding what exactly you're trying to test (hopefully it's not IBMMQ itself) hence cannot come up with comprehensive solution, the options I can think of are in:

    1. Each JMeter thread (virtual user) is a separate upstream component which sends messages to the IBMMQ instance, in this case you need to create a Producer instance per virtual user. Just add current thread number as a prefix or postfix to the properties holding the sessions, i.e. instead of:

      props.put("SessionInbound", sessInboundQueue)
      

      do something like:

      props.put("SessionInbound_" + ctx.getThreadNum(), sessInboundQueue)
      

      where ctx stands for JMeterContext class instance, see JavaDoc for full documentation on all possible functions

    2. Opening a connection is quite an "expensive" process that's why normal developers go for Connection Pool pattern, most probably real producers will have this implemented somehow so you need to know the details and configure your JMeter script accordingly. Check out Connection pooling in IBM MQ classes for Java and Examples of using the connection pool. If you like to copy and paste the code you can get some from Supplying a different connection pool in IBM MQ classes for Java page