8 Replies Latest reply on Nov 20, 2014 11:55 AM by jbertram

    Queue Messaging behaviour on JBoss 6

    abhinbalur

      Pretty new to messaging/JMS on JBoss; need some help.

      I am noticing different behaviour for Queue based messaging for a sample queue on JBOSS 4.2.3 and JBOSS 6.

      Lets say there is a sample jms queue called "SampleQueue" and consumers consuming messages from it. In a working environment with Jboss 4.2.3 when i add messages to the SampleQueue; the consumers seem to be picking them up instantly.

      However the same is not achieved in JBOSS 6.1. What i notice in JBOSS 6.1 is a consumer blocks till it receives acknowledgment or finishes processing for the previous message posted on the queue.

      For example:-

      If message M1 and M2 are pushed to the queue; in that order; M2 is not picked up by a consumer till "onMessage" call for M1 returns. In other words M2 is not picked up till M1 is processed and an acknowledgment sent.

      How can i avoid this?

      Its a non transacted; non durable queue we are talking about here. And a producer producing multiple messages with more than one consumer.

      What i have tried so far:-

      1. Sending an explicit ack using the acknowledge method.
      2. setting "block-on-non-durable-send" to false in the hornetq-jms.xml.

      My MDB config looks as below:-

      @MessageDriven(activationConfig = {  @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/SampleQueue"), @ActivationConfigProperty(propertyName = "messageSelector", propertyValue = "MessageFormat = 'Version 0.1' AND Service = 'SampleImpl'"  ) })  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 

      I have also tried with maxSessions mdb property and setting explictly a strict pool of size 10 but to no avail.

      Let me know of any other details that i need to add. Help greatly appreciated.

        • 1. Re: Queue Messaging behaviour on JBoss 6
          jbertram

          This is likely cause by message buffering by the consumer.  Try setting the consumer-window-size for your consumer(s) to "0" to disable buffering.  Read more about this in the documentation.

          • 2. Re: Queue Messaging behaviour on JBoss 6
            abhinbalur

            Hi Justin,

             

            Thanks for your reply. But setting it to '0' did not help. Any other suggestions?

            • 3. Re: Queue Messaging behaviour on JBoss 6
              jbertram

              Can you provide me with a test-case I can use to reproduce the behavior you're seeing?

              • 4. Re: Re: Queue Messaging behaviour on JBoss 6
                abhinbalur

                I see posts all over the internet about setting consumer window size to 0 to get this working; but frustratingly this doesnt seem to working in my case.

                 

                So i am not sure if you will actually be able to reproduce the issue.

                 

                Nevertheless this is what i have:-

                 

                Prerequisites:-

                 

                1) Jboss 6.1.0 Final

                 

                2) Use JMS API and not the core horentq api.

                 

                Steps:(In a working jboss setup)

                 

                -- In a Stateless Session Bean(SSB) create a method for producing messages onto a Queue.

                Message is sent with following code:-

                final Session session =

                                connect.createSession( false, Session.AUTO_ACKNOWLEDGE );

                            final MessageProducer sender =

                                session.createProducer( requestQueue );

                            final ObjectMessage message = session.createObjectMessage();

                            message.setStringProperty( "MessageFormat", "Version 0.1" );

                            message.setStringProperty( "Service", "ServiceCallerJms" );                       

                            message.setObject( JMSUtils.getBytes(messageObject) );

                            sender.setDeliveryMode( DeliveryMode.NON_PERSISTENT );

                            sender.send( message );

                -- The connectionfactory ("/ConnectionFactory ") is looked up using JNDI.

                 

                This is how my connectionfactory config looks in hornetq-jms.xml

                <connection-factory name="NettyConnectionFactory">

                    <block-on-non-durable-send>false</block-on-non-durable-send>

                    <block-on-durable-send>false</block-on-durable-send>

                      <connectors>

                         <connector-ref connector-name="netty"/>

                      </connectors>

                      <entries>

                         <entry name="/ConnectionFactory"/>

                         <entry name="/XAConnectionFactory"/>

                      </entries>

                      <consumer-window-size>0</consumer-window-size>

                   </connection-factory>

                  

                   <connection-factory name="NettyThroughputConnectionFactory">

                       <connectors>

                         <connector-ref connector-name="netty-throughput"/>

                       </connectors>

                        <entries>

                            <entry name="/ThroughputConnectionFactory"/>

                            <entry name="/XAThroughputConnectionFactory"/>

                        </entries>

                        <consumer-window-size>0</consumer-window-size>

                    </connection-factory>

                  

                   <connection-factory name="InVMConnectionFactory">

                       <block-on-non-durable-send>false</block-on-non-durable-send>

                    <block-on-durable-send>false</block-on-durable-send>

                      <connectors>

                         <connector-ref connector-name="in-vm"/>

                      </connectors>

                      <entries>

                         <entry name="java:/ConnectionFactory"/>

                         <entry name="java:/XAConnectionFactory"/>

                      </entries>

                      <consumer-window-size>0</consumer-window-size>

                   </connection-factory>

                 

                   <connection-factory name="avmgmt">

                    <block-on-non-durable-send>false</block-on-non-durable-send>

                    <block-on-durable-send>false</block-on-durable-send>

                      <connectors>

                         <connector-ref connector-name="in-vm"/>

                      </connectors>

                      <entries>

                         <entry name="jms/avaya/mgmt/connectionFactory"/>

                      </entries>

                      <consumer-window-size>0</consumer-window-size>

                   </connection-factory>

                --  Have consumers written implementing MessageListener with config/annotations as mentioned in the original question/post.

                 

                -- Write the first message on to the Queue. This first message takes significantly more time to finish its processing. Close to 4-5 minutes. Lets call this Window1

                 

                -- While the first message is being processed(that is immediately after first 30 seconds of Window1) in the "onMessage" method; produce/push another message onto the Queue.

                 

                What you should observe now is that the second message is picked up by a consumer AFTER the Window1 period. However on jboss 4.2.3 (JBOSS MQ) the consumer picks the message as soon as you push it on the queue. I want the same behaviour that you see on jboss 4.2.3.

                 

                Let me know if you need anything else. Thanks a lot!

                • 5. Re: Re: Queue Messaging behaviour on JBoss 6
                  jbertram

                  So are your consumers MDBs?  If so, you should set the "consumerWindowSize" activation configuration property since it is a consumer setting.  Setting that value on the connection factory used by the producer does nothing for the consumer.

                  • 6. Re: Re: Queue Messaging behaviour on JBoss 6
                    jbertram

                    By the way, is this a valid use-case for your application?  Is your message volume actually going to be this low, and are your consumers going to actually be this slow?  The message pre-fetching is a network optimization for high-volume message throughput so if you pushed more messages through at a higher rate you would probably see this even out.

                    • 7. Re: Queue Messaging behaviour on JBoss 6
                      abhinbalur

                      Hi Justin,

                       

                      Thanks a lot. Setting it on the MDB through a activation property worked. I was more inclined towards the name "consumer" in the property "consumerWindowSize", misleading me to believe its a consumer property set on connection factory even in case of MDB's.

                       

                      By the way to answer about your question on the usecase; the consumers could range anywhere from 1 to thousands; and few parts of the system spawning  a  few slow consumers taking a few minutes to complete; along with few fast consumers.

                       

                      My question now is if setting consumer window size solved the problem; does it mean in the testcase i have described the same consumer was picked later again since its buffer was not full? Why werent other consumers picked instantly in a round robin fashion?

                      • 8. Re: Queue Messaging behaviour on JBoss 6
                        jbertram

                        Setting it on the MDB through a activation property worked. I was more inclined towards the name "consumer" in the property "consumerWindowSize", misleading me to believe its a consumer property set on connection factory even in case of MDB's.

                        The consumerWindowSize property is a consumer property.  That's why you should set it on the MDB's activation configuration properties since your MDBs are your consumers.  MDBs don't use connection factories like traditional JMS clients so setting consumer-window-size on the connection factories doesn't help.  If you had traditional JMS consumers that were using connection factories then it would help, but apparently you don't.

                         

                        By the way to answer about your question on the usecase; the consumers could range anywhere from 1 to thousands; and few parts of the system spawning  a  few slow consumers taking a few minutes to complete; along with few fast consumers.

                        In that case you should take care how you set the consumer-window-size for each of your consumers otherwise you could incur a performance penalty from unnecessary network round-trips and/or consumer starvation.

                         

                        My question now is if setting consumer window size solved the problem; does it mean in the testcase i have described the same consumer was picked later again since its buffer was not full?

                        I believe a single consumer was getting both messages - consuming one immediately and buffering the other - so that the other consumer was starved.

                         

                        Why werent other consumers picked instantly in a round robin fashion?

                        The broker doesn't pick which consumer gets a message because the broker doesn't know the performance characteristics of each consumer.  The broker expects the consumer to set its consumer-window-size intelligently so that it's not greedy.  Message consumption is essentially first-come-first-serve.