3 Replies Latest reply on Oct 2, 2014 12:08 PM by jbertram

    MDB implementation using anti-pattern ?

    janssk77

      Quoting the HornetQ performance doc:

       

      Re-use connections / sessions / consumers / producers. Probably the most common messaging anti-pattern we see is users who create a new connection/session/producer for every message they send or every message they consume. This is a poor use of resources. These objects take time to create and may involve several network round trips. Always re-use them.

       

      When using the hornetq-ra inside jboss, this is exactly what happens.

      I have a MDB listening on a queue. Jboss is configured to have 50 consumers on this queue. I have noticed that the resource adapter creates 50 session factories, implying 50 hornetq remoting connections and 100 InVmConnections. Since there are 50 session factories, jboss also schedules 50 pings generating a substantial amount of load. This pings can be disabled but it's still weird to have 50 session factories.

       

      This gets even worse when more MDB's are added. We have about 10 MDB's in our system, leading to 500 session factories, 500 remoteconnections etc...

       

      Root cause is the HornetQActivation.setup implementation:

       

      for (int i = 0; i < spec.getMaxSession(); i++)
         {
         ClientSessionFactory cf = null;
         ClientSession session = null;
         try
         {
         cf = factory.getServerLocator().createSessionFactory();
         session = setupSession(cf);
         HornetQMessageHandler handler = new HornetQMessageHandler(this, ra.getTM(), (ClientSessionInternal) session, cf, i);
         handler.setup();
         handlers.add(handler);

       

      IMHO, the sessionfactory creation should not happen inside the for loop.

       

      Actually, the same session factory could even be shared across all MDB's (instead of 500 SF i would end up with only a single one)

      Another optimization could use only a single session to 'feed' all (50) instances of an MDB, but that would have to be a configurable setting...

       

      Thoughts ?

       

      Koen

      PS: I'm using hornet 2.3.5 (inside jboss EAP 6.1.1), but the code snippet is from trunk.

        • 1. Re: MDB implementation using anti-pattern ?
          jbertram

          Re-use connections / sessions / consumers / producers. Probably the most common messaging anti-pattern we see is users who create a new connection/session/producer for every message they send or every message they consume. This is a poor use of resources. These objects take time to create and may involve several network round trips. Always re-use them.

           

          When using the hornetq-ra inside jboss, this is exactly what happens.

          This is not what happens in the HornetQ JCA RA.  A new connection, session, and consumer is not created for every message that is consumed.  Each MDB instance has it's own connection, session, and consumer which is re-used for every message consumed.

           

          That said, each logical MDB could probably have a single ClientSessionFactory instance (i.e. a connection in JMS terms) so that all the instances of said MDB would share that one ClientSessionFactory.  However, a single ClientSessionFactory wouldn't be shared across different logical MDBs as they would likely be configured in mutually exclusive ways.  Even if the MDBs weren't configured in mutually exclusive ways so that they might be able to share a common ClientSessionFactory I doubt such an optimization would be worth the investment to implement and maintain it.

           

          Furthermore, you could not have a single ClientSession instance per logical MDB as a ClientSession is not thread-safe (i.e. it should not be used concurrently by multiple threads which is exactly what happens in the typical MDB use-case).  Also, later versions of HornetQ have connection monitoring (i.e. pings/pongs) disabled for in-vm connections.  See HORNETQ-1314.

           

          So now in the case where you have 10 different MDBs each configured with a maxSession of 50 you have 500 (10 * 50) ClientSessionFactory instances and 500 ClientSession instances which correspond 1:1 with the 500 MDB instances.  If we implemented a shared ClientSessionFactory then in the same scenario you would have 10 ClientSessionFactory instances and 500 ClientSession instances for the 500 MDB instances.

          • 2. Re: MDB implementation using anti-pattern ?
            janssk77

            You are right. The RA adapter is not creating a new session per message. I should not have referenced that document.

             

            I also second that sharing a sessionfactory across different MDB and reusing a session might not be worth the effort.

             

            Using a single sessionfactory (which I relatively 'heavy' object) for a single MDB sounds like a valuable improvement

             

            Thanks,

             

            Koen

            • 3. Re: MDB implementation using anti-pattern ?
              jbertram

              Following up on this...

               

              I was looking at changing the HornetQ JCA RA logic so that just one ClientSessionFactory would be created per MDB when I spoke with one of my colleagues.  The reason that there is currently a 1:1 ratio between ClientSessionFactory:ClientSession is due to load-balancing concerns when a MDB might be consuming from a remote cluster.  Rather than having all the MDB session pile up on a single node of a cluster they will be spread across the nodes more evenly.  Until I see evidence that this poses a statistically significant performance problem for the local use-case I don't plan on changing the logic.