ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum IndexIBM MQ Java / JMSMQJMS API, how to get the queue depth without using browser

Post new topicReply to topic Goto page 1, 2  Next
MQJMS API, how to get the queue depth without using browser View previous topic :: View next topic
Author Message
abhay09
PostPosted: Tue May 31, 2016 3:50 am Post subject: MQJMS API, how to get the queue depth without using browser Reply with quote

Apprentice

Joined: 31 May 2016
Posts: 47

HI,

I am using MQJMS API to connect to MQ v8.0

AS per our requirement, we are pooling MQ Queue based on its depth i,e creating threads based on depth.

For this using a QueueBrowser enumeration and counting messages.

this is working fine for few messages in queue but giving a performance blocker if queue have many messages like (>1000).

Please let me know how we can find queue depth of MQ Queue using MQJMS API.
and similar method like queue.currentDepth in MQ JAVA lib.

Any help will be appreciated.

Thanks
Abhay
Back to top
View user's profile Send private message
mqjeff
PostPosted: Tue May 31, 2016 4:17 am Post subject: Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 16835

Trying to code any kind of MQ application to make decisions of any sort on q depth is an anti-pattern.

It's very easy for the depth of a queue to be n when you check, and then an entirely different value m when you go to try and read messages, and then a third different value p during the time you are reading messages.

When working with JMS, you should ideally just use MDBs and not worry about how many messages are on the queue.

If you're not using an environment that can run MDB's, you should still simply read messages - and not count the queue depth and not use browse.
_________________
Read, Think, Try, Repeat
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Tue May 31, 2016 4:55 am Post subject: Reply with quote

Grand Poobah

Joined: 18 Nov 2003
Posts: 18860
Location: LI,NY

Where I may understand the need to check queue depth to spool up additional consumers, the only correct way you'd be doing that is described in Using PCF with MQ JMS
Note that you may have to use PCFHeaders due to CCSID implications...
Have fun
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
abhay09
PostPosted: Tue May 31, 2016 6:04 am Post subject: Reply with quote

Apprentice

Joined: 31 May 2016
Posts: 47

Ok, I will try this approach and let you know.

Thanks!
Back to top
View user's profile Send private message
gbaddeley
PostPosted: Tue May 31, 2016 4:25 pm Post subject: Reply with quote

Padawan

Joined: 25 Mar 2003
Posts: 1564
Location: Melbourne, Australia

Quote:
For this using a QueueBrowser enumeration and counting messages.
this is working fine for few messages in queue but giving a performance blocker if queue have many messages like (>1000).

This is a very bad design. Never browse queues to count messages. There is a MQ API to inquire on the current depth. Use this! An MQ PCF call is not required.

There are very few app designs that actually require knowledge of current depth. The usual design is to "consume all messages as soon as possible to zero depth".

On busy queues, the depth will go up and down at a fast rate, so knowing the current depth is not useful if 1 millisecond later it has changed by a large amount.
Quote:
Where I may understand the need to check queue depth to spool up additional consumers

Its actually more efficient to run a fixed number of consumers. MQ will keep one of them busy consuming messages, and then start using others when required. The "idle" consumers will not be using any CPU resources.
_________________
Glenn
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Wed Jun 01, 2016 4:39 am Post subject: Reply with quote

Grand Poobah

Joined: 18 Nov 2003
Posts: 18860
Location: LI,NY

gbaddeley wrote:
Quote:
For this using a QueueBrowser enumeration and counting messages.
this is working fine for few messages in queue but giving a performance blocker if queue have many messages like (>1000).

This is a very bad design. Never browse queues to count messages. There is a MQ API to inquire on the current depth. Use this! An MQ PCF call is not required.

This API call is not available in JMS. So yes you will have to go the PCF route if you are using JMS. I had to go that route trying to determine/display the number of ipprocs from a web server...

gbaddeley wrote:
There are very few app designs that actually require knowledge of current depth. The usual design is to "consume all messages as soon as possible to zero depth".

On busy queues, the depth will go up and down at a fast rate, so knowing the current depth is not useful if 1 millisecond later it has changed by a large amount.
Quote:
Where I may understand the need to check queue depth to spool up additional consumers

Its actually more efficient to run a fixed number of consumers. MQ will keep one of them busy consuming messages, and then start using others when required. The "idle" consumers will not be using any CPU resources.

And don't forget to have each consumer run in it's own session...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
abhay09
PostPosted: Thu Jun 02, 2016 12:17 am Post subject: Reply with quote

Apprentice

Joined: 31 May 2016
Posts: 47

fjb_saper wrote:
gbaddeley wrote:
Quote:
For this using a QueueBrowser enumeration and counting messages.
this is working fine for few messages in queue but giving a performance blocker if queue have many messages like (>1000).

This is a very bad design. Never browse queues to count messages. There is a MQ API to inquire on the current depth. Use this! An MQ PCF call is not required.

This API call is not available in JMS. So yes you will have to go the PCF route if you are using JMS. I had to go that route trying to determine/display the number of ipprocs from a web server...

gbaddeley wrote:
There are very few app designs that actually require knowledge of current depth. The usual design is to "consume all messages as soon as possible to zero depth".

On busy queues, the depth will go up and down at a fast rate, so knowing the current depth is not useful if 1 millisecond later it has changed by a large amount.
Quote:
Where I may understand the need to check queue depth to spool up additional consumers

Its actually more efficient to run a fixed number of consumers. MQ will keep one of them busy consuming messages, and then start using others when required. The "idle" consumers will not be using any CPU resources.

And don't forget to have each consumer run in it's own session...



Hi Guys,

Thanks for the reply.
I tried to get the depth using PCF headers.

However, with this code also I am not getting the depth parameter.

Please find below my test code and let me know how can i get the depth.



package com.sec;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.util.Enumeration;

import javax.jms.BytesMessage;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSProducer;
import javax.jms.Queue;

import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.headers.pcf.MQCFH;
import com.ibm.mq.headers.pcf.PCFMessage;
import com.ibm.mq.jms.MQQueue;
import com.ibm.mq.jms.MQXAConnectionFactory;
import com.ibm.msg.client.jms.JmsConstants;
import com.ibm.msg.client.wmq.WMQConstants;

public class PCFAgentTest {
private final static String hostname = "localhost";
private final static int port = 1415;
private final static String channel = "SVRCONN";
private final static String qManager = "MQTest";
private final static String qName = "MQReceiverQueue";

public static void main(String[] args) {
try {

MQXAConnectionFactory mqConnectionFactory = new MQXAConnectionFactory();

mqConnectionFactory.setHostName(hostname);
mqConnectionFactory.setChannel(channel);
mqConnectionFactory.setPort(port);
mqConnectionFactory.setQueueManager(qManager);
mqConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);

JMSContext ctx = mqConnectionFactory.createContext();

Queue q1 = ctx.createQueue("SYSTEM.ADMIN.COMMAND.QUEUE");
((MQQueue) q1).setIntProperty(WMQConstants.WMQ_MESSAGE_BODY,
WMQConstants.WMQ_MESSAGE_BODY_MQ);
((MQQueue) q1).setMQMDWriteEnabled(true);
((MQQueue) q1).setMQMDReadEnabled(true);

final BytesMessage msg = ctx.createBytesMessage();

// Create the wrapping streams to put the bytes into the message
// payload
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutput dataOutput = new DataOutputStream(baos);
MQCFH header = new MQCFH();

header.setCommand(CMQCFC.MQCMD_INQUIRE_Q_STATUS);
// Set the JMSReplyTo so the answer comes back
msg.setJMSReplyTo(ctx.createTemporaryQueue());
PCFMessage pcfCmd = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q_STATUS);
// Specify the name of the queue,
pcfCmd.setHeader(header);
pcfCmd.addParameter(CMQC.MQCA_Q_NAME, qName);

// and that we want to find out its depth.
pcfCmd.addParameter(CMQCFC.MQIACF_Q_STATUS_ATTRS,
new int[] { CMQC.MQIA_CURRENT_Q_DEPTH });

pcfCmd.write(dataOutput);
baos.flush();
msg.writeBytes(baos.toByteArray());

// we have taken control of the MD, so need to set all
// flags in the MD that we require - main one is the format
msg.setJMSPriority(4);
msg.setIntProperty(WMQConstants.JMS_IBM_MQMD_PERSISTENCE,
CMQC.MQPER_NOT_PERSISTENT);
msg.setIntProperty(WMQConstants.JMS_IBM_MQMD_EXPIRY, 300);
msg.setIntProperty(WMQConstants.JMS_IBM_MQMD_REPORT,
CMQC.MQRO_PASS_CORREL_ID);
msg.setStringProperty(WMQConstants.JMS_IBM_MQMD_FORMAT, "MQADMIN");
msg.setIntProperty(JmsConstants.JMS_IBM_MQMD_CODEDCHARSETID, 500);
JMSProducer jmsProducer = ctx.createProducer();

jmsProducer.send(q1, msg);

JMSConsumer consumer = ctx.createConsumer(msg.getJMSReplyTo());

BytesMessage message = (BytesMessage) consumer.receive();
// System.out.println(message);
// get the size of the bytes message & read into an array
int bodySize = (int) message.getBodyLength();
byte[] data = new byte[bodySize];
message.readBytes(data);

// Read into Stream and DataInput Stream
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInput dataInput = new DataInputStream(bais);

// Pass to PCF Message to process
PCFMessage response = new PCFMessage(dataInput);
Enumeration qDepthParm = response.getParameters();

// System.out.println(response);

while (qDepthParm.hasMoreElements()) {
System.out.println(qDepthParm.nextElement());
}

ctx.close();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}



Please look at the code and rectify my mistake.

Please help!!

Thanks!
Back to top
View user's profile Send private message
Vitor
PostPosted: Thu Jun 02, 2016 4:41 am Post subject: Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 24031
Location: Ohio, USA

abhay09 wrote:
I tried to get the depth using PCF headers.


This is still (as others have mentioned) a really, really bad design. If you're committed to this very bad requirement of starting new consumers on demand (which sounds like a business / management requirement than a technical one to me) consider using service or queue events.

abhay09 wrote:
Please find below my test code and let me know how can i get the depth.


How do you know you didn't get it?
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Jun 02, 2016 4:56 am Post subject: Reply with quote

Grand Poobah

Joined: 18 Nov 2003
Posts: 18860
Location: LI,NY

Depending on your system there is a problem with the Encoding. I hit that one on Windows (little Endian) as the bytestream you retrieved from the reply does not take into account the Encoding. A CCSID should also be specified?

For this I had to use the pcfHeader which allows you to pass into the constructor a CCSID and Encoding... and then create the pcf message from the header chain...
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
mqjeff
PostPosted: Thu Jun 02, 2016 6:04 am Post subject: Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 16835

I'm not sure why you aren't just using the PCF Java classes.
_________________
Read, Think, Try, Repeat
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Jun 02, 2016 6:26 am Post subject: Reply with quote

Grand Poobah

Joined: 18 Nov 2003
Posts: 18860
Location: LI,NY

mqjeff wrote:
I'm not sure why you aren't just using the PCF Java classes.

Tried that from within an application server and fell down on my backside. No reliable connection syndrome...
Had to use JMS, and my connections became reliable... it's magic!!!
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
mqjeff
PostPosted: Thu Jun 02, 2016 6:44 am Post subject: Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 16835

You should still be able to construct PCFMessage objects.
_________________
Read, Think, Try, Repeat
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Thu Jun 02, 2016 8:45 am Post subject: Reply with quote

Grand Poobah

Joined: 18 Nov 2003
Posts: 18860
Location: LI,NY

Indeed I did. However it likes the stream to be in big endian. If your stream happens to be in little endian there is an exception being thrown...

Unless you specify endian-ness with the stream (like full MQ Message and not just the bytes from the byte message.

Hence the need to load the pcfHeaders / MQHeaders with the stream and provide endian characteristics.... You can then output from the Headers to a DataOutput / DataInput and create the PCFMessage....
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
abhay09
PostPosted: Thu Jun 02, 2016 8:53 am Post subject: Reply with quote

Apprentice

Joined: 31 May 2016
Posts: 47

Hi Guys,


I searched and read docs and found out they have PCFAgent that is very handy to query MQ.

I wrote code and tested to get depth, it worked well.
Please find the code below:




import java.io.IOException;

import com.ibm.mq.MQException;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.constants.CMQCFC;
import com.ibm.mq.pcf.PCFMessage;
import com.ibm.mq.pcf.PCFMessageAgent;


public class PCFAgentClass {

private final static String hostname = "localhost";
private final static int port = 1415;
private final static String channel = "SVRCONN";
private final static String qName = "MQReceiverQueue";

public static void main(String[] args) throws MQException, IOException {

PCFMessageAgent agent = new PCFMessageAgent(hostname, port, channel);

PCFMessage request = new PCFMessage (CMQCFC.MQCMD_INQUIRE_Q);
request.addParameter (CMQC.MQCA_Q_NAME, qName);
request.addParameter (CMQCFC.MQIACF_Q_ATTRS,
new int [] { CMQC.MQCA_Q_NAME, CMQC.MQIA_CURRENT_Q_DEPTH , CMQC.MQIA_Q_TYPE});

// Use the agent to send the request

System.out.print ("Sending PCF request... ");
PCFMessage [] responses = agent.send (request);
System.out.println ("Received reply.");

for (int i = 0; i < responses.length; i++)
{
String name = responses [i].getStringParameterValue (CMQC.MQCA_Q_NAME);
int depth = responses [i].getIntParameterValue (CMQC.MQIA_CURRENT_Q_DEPTH);

int type = responses [i].getIntParameterValue (CMQC.MQIA_Q_TYPE);

System.out.println ("Queue " + name + " curdepth " + depth +" queue type " + type);
}

agent.disconnect();

}

}

By this code , I am able to get the depth and other stuff like queue type.

So, shall i use this approach to get depth in MQJMS and poll Mq queue based on the depth (number of threads will be based on depth)?

Experts , Pls guide shall i use this agent to get depth ?
Back to top
View user's profile Send private message
abhay09
PostPosted: Thu Jun 02, 2016 8:56 am Post subject: Reply with quote

Apprentice

Joined: 31 May 2016
Posts: 47

mqjeff wrote:
I'm not sure why you aren't just using the PCF Java classes.



PCF classes, use mean to say PCFAgent?
Like this?

PCFMessageAgent agent = new PCFMessageAgent(hostname, port, channel);

PCFMessage request = new PCFMessage (CMQCFC.MQCMD_INQUIRE_Q);
request.addParameter (CMQC.MQCA_Q_NAME, qName);
request.addParameter (CMQCFC.MQIACF_Q_ATTRS,
new int [] { CMQC.MQCA_Q_NAME, CMQC.MQIA_CURRENT_Q_DEPTH , CMQC.MQIA_Q_TYPE});

?
Back to top
View user's profile Send private message
Display posts from previous:
Post new topicReply to topic Goto page 1, 2  Next Page 1 of 2

MQSeries.net Forum IndexIBM MQ Java / JMSMQJMS API, how to get the queue depth without using browser
Jump to:



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP


Theme by Dustin Baccetti
Powered by phpBB 2001, 2002 phpBB Group

Copyright MQSeries.net. All rights reserved.