12 Replies Latest reply on Aug 10, 2007 6:14 AM by aslak

    Grouping of messages with JMSXGroupId(JBMESSAGING-375)

    hegsti

      Hi, I'm trying to do my first contribution to JBoss Messaging so be nice :)
      I worked on a project last year where message groups (messages with the same group id always go to the same consumer on a queue).
      would have been really useful. I just finished a working proof of concept, which I hope to complete with help and feedback.

      To continue to support the default round robin routing when JMSXGroupID is not supplied, I modified the existing RoundRobinPointToPointRouter to route based on given JMSXGroupID when supplied.

      The Delivery handle(...) now behaves like this:
      ..
      ..
      get the reciver by round robin. if a groupId is given, try to see if a receiver is already assigned to handle this group.
      If it is, use this to deliver.
      Else bind the receiver given by round robin to the groupId in the message.
      deliver using this receiver.

      If the receiver is broken, remove the binding between the current receiver and the groupId.
      ...
      ...

      This approach will ensure that round robin works as before, and that each consumer will have an equal chance to be bound to spesific groups. If a receiver is broken, the mapping will be removed and a new receiver will be selected to handle the group.

      To support a large number of groups in an efficient way, I decided not to use some kind of map which grows for each new group that needs a mapping to a receiver.

      The current solution uses a large Receiver array. Ie. 1000 elements.

      Receiver[] receiverGroupMapping = new Receiver[1000];

      A mapping between a groupId and a receiver is then resolved by Math.abs(groupId.hashCode() % receiverGroupMapping.length).
      The returned number will be the position in the receiverGroupMapping to insert,get or remove a receiver from.

      The large array and usage of hashCode from the String should give a nice distribution of receivers for groupId's even when there are extremely large number of groups.

      In the spec, all that is mentioned about JMSXGroupId (see 3.5.9 JMS Defined Properties):

      "JMSXGroupID and JMSXGroupSeq are standard properties clients should use if they want to group messages. All providers must support them. "

      The actual semantics of the JMSXGroupSeq is not mentioned, so for now it is not used for anything.

      I don't know if this is how you want this implemented, but I hope it's at least enough to get a discussion started :).

      Inside the router I use ref.getMessage().getHeader("PJMSXGroupID") to get the groupId, since JMSXGroupID is a JMS spesific property
      it might be forbidden to know about this property inside core of messaging ?

      I have not explored if my changes breaks anything in a clustered environment etc.


      Stian Hegglund

        • 1. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
          timfox

          I haven't forgotten about you, but I'm just maxed out getting 1.2.0.SP2 together. :)

          I will have a think about this after we release.

          • 2. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
            timfox

             

            "hegsti" wrote:
            Hi, I'm trying to do my first contribution to JBoss Messaging so be nice :)
            I worked on a project last year where message groups (messages with the same group id always go to the same consumer on a queue).
            would have been really useful. I just finished a working proof of concept, which I hope to complete with help and feedback.


            Great. Message groups are a nice feature that have been on our road map for some time. http://jira.jboss.com/jira/browse/JBMESSAGING-375


            To continue to support the default round robin routing when JMSXGroupID is not supplied, I modified the existing RoundRobinPointToPointRouter to route based on given JMSXGroupID when supplied.


            I agree it should be based on the RoundRobinRouter, but I would prefer to see it implemented in its own class e.g. GroupingRoundRobinPointToPointRouter. Maybe you can extend RoundRobinPointToPointRouter?


            The Delivery handle(...) now behaves like this:
            ..
            ..
            get the reciver by round robin. if a groupId is given, try to see if a receiver is already assigned to handle this group.
            If it is, use this to deliver.
            Else bind the receiver given by round robin to the groupId in the message.
            deliver using this receiver.

            If the receiver is broken, remove the binding between the current receiver and the groupId.

            Where does the message go, if the receiver is broken?
            ...
            ...

            This approach will ensure that round robin works as before, and that each consumer will have an equal chance to be bound to spesific groups. If a receiver is broken, the mapping will be removed and a new receiver will be selected to handle the group.



            Ok, makes sense.


            To support a large number of groups in an efficient way, I decided not to use some kind of map which grows for each new group that needs a mapping to a receiver.


            Personally I would just use a HashMap. HashMaps work on pretty much the same principle as you are suggesting anyway: I.e. they maintain an array and use the hashCode to detemine the lookup in the array - also they manage their own resizing so you don't have to worry about it.

            I would be surprised if a HashMap was much slower than what you are suggesting.

            I would be careful of doing premature optimisations.

            Thanks Stian



            • 3. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
              timfox

              Hello Stian-

              How's this work going?

              • 4. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                hegsti

                Hello Tim, I have been busy for some days, but I'm almost finished :). I have to write some more tests, and
                I also have some minor work to do when it comes to handle messages rejected by selectors.

                I'll run some extreme test cases and send you a patch later this week.
                It's probably things I haven't thought about, but it is a starting point :).

                Stian

                • 5. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                  timfox

                  Do you have a skype/yahoo id?

                  • 6. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                    hegsti

                    Hi, my skype id is stian.hegglund.

                    • 7. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                      hegsti

                      I have attached a patch for MessageGroupRouting (JBMESSAGING-375) in JIRA.
                      The patch contains the new Router, some tests, a temporary modification of PagingFilteredQueue.java ( to enable the new Router), and some modifications to the RoundRobinPointToPointRouter to extend it.

                      This should NOT be considered as a final patch, but it should be enough to demonstrate a working solution I can improve and complete based on feedback.

                      There are two minor things left (which I'm currently aware of :) ).

                      1)A way to enable the router by configuration, so that the PagingFilteredQueue can create a router based on this configuration.
                      Maybe a mbean attribute on the queue configuration <consumer-routing-policy>message-group-routing</consumer-routing-policy> or something ?

                      2) I should also try to make the algorithm more readable and avoid some code duplication.

                      I have done some testing to simulate different scenarios where receivers are closing and client side buffers gets full. But there may be scenarios I have not thought about :).

                      Stian

                      • 8. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                        timfox

                        Ok, thx Stian - I will take a look at this soon.

                        • 9. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                          timfox

                          Thanks Stian-

                          I think we should add an attribute on the server "enableMessageGrouping".

                          And then just use the message grouping router by default.

                          If you get your final changes together, someone will integrate it into TRUNK, then I shall add you to the contributors list.


                          • 10. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                            hegsti

                            Hi, I'll get my final changes together later this week.
                            Btw. would it be ok to add a Distributor factory that looks up the new ServerPeer MBean attribute to decide if the grouping distributor should be used ?

                            Stian

                            • 11. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                              timfox

                              Sorry it's taken so long to get back to you, we've been really busy recently getting 1.4.0.CR1 out.

                              I don't think there's any need for a factory - we can just add a flag "enableMessageGrouping" to the serverpeer and use the grouping router by default.

                              • 12. Re: Grouping of messages with JMSXGroupId(JBMESSAGING-375)
                                aslak

                                How about adding support on the server for the JMSXGroupSeq as well.
                                Ensuring that messages are delivered in sequence to the same consumer.

                                Not sure what to do if they don't come in sequence,.. Maybe a TTL could handle it.