8 Replies Latest reply on Oct 10, 2012 5:02 AM by Andy Taylor

    HornetQ Queue order

    javahamburg Newbie

      Hi, I have a problem here regarding the order of messages in a durable JMS Queue.

      We have a system where the sequence of messages is critical, and as long the consumer is running, they come in the correct order in which the producer creates them. The messages should be redelivered in case of failure, so no message should be lost (duplicates are not a problem if there is a question about that).

      But when the consumer fails, the order gets messed up. I use only one consumer, and I'm using MessageGroups.

      Beside acknowledgeMode CLIENT_ACKNOWLEDGE I tried transactions as well.

       

      I added some simplified sample code to help reproducing. I use a clean HornetQ 2.2.5.Final, with following additions:

       

      Added in hornetq-configuration:

      <redelivery-delay>1000</redelivery-delay>
      <max-delivery-attempts>-1</max-delivery-attempts>
      

       

      Added in hornetq-jms.xml

      <queue name="testing">
         <entry name="/queue/testing" />
         <durable>true</durable>
      </queue>
      

       

       

      In the code I produce 50 sequential messages, then they will be tried to consume, which fails in the first place.

      The order is not correct, I expect that only the first message is consumed, until acknowledged.

      While the programm is running (and failing), you restart hornetq.

      Now the messages are in order. I have cases where this not the case, but I didn't find out how to reproduce this yet.

       

      Sorry for being confusing maybe, but It is hard to abstract code that reproduces the issue I have here.

      Thanks in advance, I keep investigating.

        • 1. Re: HornetQ Queue order
          Andy Taylor Master

          you are rolling back the message which mark s it as redelivered, since your redelivery delay is 1000ms this message will be delayed allowing the other messages to be delivered first.

          • 2. Re: HornetQ Queue order
            Clebert Suconic Master

            I just tried your sample. Set consumerWindowSize(0) at your connection factory. There's a buffer on the client, and the entire buffer is being rolled back, and messages are being sent to DLA upon max-redelivery. ON my case these messages were just being dumped since it was configured to drop on my case.

            • 3. Re: HornetQ Queue order
              javahamburg Newbie

              Ok, this seems to solve the issue.

              But it generates a new one. How can I ensure that the client/server is not overloaded with failing messages, since I want that the failing message keeps retrying (which is my requirement)? I expect that the client now has to handle this timeout, or is there a configuration property for that? Section 21.1. (Delayed Redelivery) tells me to set this property for this case, but it does not mention that messages can be skipped.

               

              It is confusing btw. that the documentation defines the default as "0" (21.1.1. Configuring Delayed Redelivery & Table 48.1. Server Configuration - in case of absence I guess). But the default configuration taken in reality is "1000" (config/stand-alone/non-clustered/hornetq-configuration.xml).

              • 4. Re: HornetQ Queue order
                Andy Taylor Master

                But it generates a new one. How can I ensure that the client/server is not overloaded with failing messages, since I want that the failing message keeps retrying (which is my requirement)? I expect that the client now has to handle this timeout, or is there a configuration property for that? Section 21.1. (Delayed Redelivery) tells me to set this property for this case, but it does not mention that messages can be skipped.

                Im not sure i understand what you mean by "overloaded with failing messages", its pretty simple if a message delivery is rolled back it will be added back to the queue after the redelivery delay, if 0 then it will be added to the head of the queue and be the next message delivered to the consumer.

                 

                Can i ask what you're use case actually is, your demo doesnt really do much apart from roll a message back.

                 

                It is confusing btw. that the documentation defines the default as "0" (21.1.1. Configuring Delayed Redelivery & Table 48.1. Server Configuration - in case of absence I guess). But the default configuration taken in reality is "1000" (config/stand-alone/non-clustered/hornetq-configuration.xml).

                The default '0' is set if it isnt configured in the hornetq-configuration.xml file, this config file is not a list of defaults but a starting point for a usable configuration.

                • 5. Re: HornetQ Queue order
                  Clebert Suconic Master

                  The only failures I saw at your test was the messages going to DLA. You can configure that... or you mean something else?

                  • 6. Re: HornetQ Queue order
                    javahamburg Newbie

                    Hi Andy,

                    Im not sure i understand what you mean by "overloaded with failing messages", its pretty simple if a message delivery is rolled back it will be added back to the queue after the redelivery delay, if 0 then it will be added to the head of the queue and be the next message delivered to the consumer.

                    Can i ask what you're use case actually is, your demo doesnt really do much apart from roll a message back.

                    in my usecase I have one producer that does send messages in a specific order to a queue. Now I want a consumer that retrieves them in the same order, therefore I use consumer.receive() to get the messages as soon they arrive. As long the consumer and producer are running without exceptions on consumer-side everything is ok. With exceptions I mean that my  consumer-client has issues processing a message. So I catch every exception inside my eventcycle and continue to the next retrieve().

                    I thought that with the configuration of the redelivery-delay the client now has to wait that time until the next message will come, which should be the same as before, since it was not acknowledged. But as you stated, the redelivery-delay is put only on the single message, and not all messages/the consumer itself. Therefore, after an exception, the messages come in high-rate to my consumer, the failed will be delayed - shuffling my order, since the not processed come first.

                    This means I have to put a sleep() on the client side.

                     

                    I used session.recover() originally, because there is no "unacknowledge" on a message, and this seems the only way not to ackowledge failed messages (since I don't want to lose a message, and acknowledge on a subsequent message will acknowledge all previous messages (what a strange specification)).

                     

                     

                    The default '0' is set if it isnt configured in the hornetq-configuration.xml file, this config file is not a list of defaults but a starting point for a usable configuration.

                    I'm aware of this, I just wanted to mention that this is confusing, since when I use a software out-of-the-box, I expect that the defaults that are documented are the defaults that I run when starting the first time. Maybe it should be mentioned in the documentation.

                     

                    Thanks

                    • 7. Re: HornetQ Queue order
                      javahamburg Newbie

                      Hi Clebert, sorry I mean something else, see above.

                      • 8. Re: HornetQ Queue order
                        Andy Taylor Master

                        in my usecase I have one producer that does send messages in a specific order to a queue. Now I want a consumer that retrieves them in the same order, therefore I use consumer.receive() to get the messages as soon they arrive. As long the consumer and producer are running without exceptions on consumer-side everything is ok. With exceptions I mean that my  consumer-client has issues processing a message. So I catch every exception inside my eventcycle and continue to the next retrieve().

                        I thought that with the configuration of the redelivery-delay the client now has to wait that time until the next message will come, which should be the same as before, since it was not acknowledged. But as you stated, the redelivery-delay is put only on the single message, and not all messages/the consumer itself. Therefore, after an exception, the messages come in high-rate to my consumer, the failed will be delayed - shuffling my order, since the not processed come first.

                        This means I have to put a sleep() on the client side.

                        If the redelivery delay is 0 then thayt will be the next message delivered, i dont see why you would need a sleep. Also you dont need to call recover or close the consumer, simply make the session SESSION_TRANSACTED and either rollback or commit the acknowledge, this is the preoper way to do this.