3 Replies Latest reply on May 24, 2012 2:31 AM by jfclere

    mod_manager and multiple virtualhosts per node

    simone.gotti

      Hi,

       

      before opening a jira I'd like to discuss about this on the forum.  I was experimenting with mod_cluster and jboss as 7.1 configured with multiple virtualhosts.

       

      My simple tests was made of a single node (as instance) with 2 virtualhosts (site01 and site02) and 2 applications respectively deployed on one of the two vhosts.

       

      I noticed that mod_manager was inserting the aliases of the 2 jboss vhosts in the same virtualhost (same vhost id):

       

       

      balancer: [1] Name: balancer01 Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 0 Timeout: 0 maxAttempts: 1

      node: [1:1],Balancer: balancer01,JVMRoute: bf3c1d57-ed66-38b4-838d-0cba532b6737,LBGroup: [],Host: 192.168.122.21,Port: 8259,Type: ajp,flushpackets: 0,flushwait: 10,ping: 10,smax: 1,ttl: 60,timeout: 0

      host: 1 [site01] vhost: 1 node: 1

      host: 2 [site02] vhost: 1 node: 1

      context: 1 [/context01] vhost: 1 node: 1 status: 1

      context: 2 [/context02] vhost: 1 node: 1 status: 1

       

       

      Now, looking at the mod_manager.c code I noticed that, inside process_appl_cmd, if the first alias name (I assume they always come in order and the first one provided in the ENABLE-APP MCMP command is always the jboss vhost default-name) doesn't exists in the hoststatsmem table then a new one is created with a fixed vhost id of 1 (as the comment says):

       

      host = read_host(hoststatsmem, &hostinfo);

          if (host == NULL) {

              int vid = 1; /* XXX: That is not really the right value, but that works most time */

       

      I tried to fix this trying to calculate the first available vhost id:

       

      @@ -1341,10 +1341,26 @@

           hostinfo.id = 0;

           host = read_host(hoststatsmem, &hostinfo);

           if (host == NULL) {

      -        int vid = 1; /* XXX: That is not really the right value, but that works most time */

      +       

               /* If REMOVE ignores it */

               if (status == REMOVE)

                   return NULL;

      +

      +        /* Find the first available vhost id */

      +        int vid = 1;

      +        int size;

      +        int *id;

      +        id = apr_palloc(r->pool, sizeof(int) * size);

      +        size = get_ids_used_host(hoststatsmem, id);

      +        for (i=0; i<size; i++) {

      +            hostinfo_t *ou;

      +            if (get_host(hoststatsmem, &ou, id[i]) != APR_SUCCESS)

      +                continue;

      +

      +            if(ou->vhost == vid && ou->node == node->mess.id)

      +                vid++;

      +        }

      +

               /* If the Host doesn't exist yet create it */

               if (insert_update_hosts(hoststatsmem, vhost->host, node->mess.id, vid) != APR_SUCCESS) {

                   *errtype = TYPEMEM;

       

       

       

      From my tests this seems to work (tried deploy, undeploy of various apps on different hosts and context). This also means that the logic inside mod_proxy_cluster looks right and correctly choose the right balancer (and sends the request to the backend only if the requested context inside the requestes vhost is defined).

       

      balancer: [1] Name: balancer01 Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 0 Timeout: 0 maxAttempts: 1

      node: [1:1],Balancer: balancer01,JVMRoute: bf3c1d57-ed66-38b4-838d-0cba532b6737,LBGroup: [],Host: 192.168.122.21,Port: 8259,Type: ajp,flushpackets: 0,flushwait: 10,ping: 10,smax: 1,ttl: 60,timeout: 0

      host: 1 [site02] vhost: 1 node: 1

      host: 2 [site01] vhost: 2 node: 1

      context: 1 [/context01] vhost: 2 node: 1 status: 1

      context: 2 [/context02] vhost: 1 node: 1 status: 1

       

       

      Then I tried adding some aliases on the jboss virtualhosts. On ENABLE it worked. Instead, during REMOVE, only the vhost default-name (the first Alias in the MCMP command) was removed keeping the other aliases and so the vhost (and giving problems during another ENABLE as it created another virtualhost only for the first alias).

       

      On ENABLE:

       

      balancer: [1] Name: balancer01 Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 0 Timeout: 0 maxAttempts: 1

      node: [1:1],Balancer: balancer01,JVMRoute: bf3c1d57-ed66-38b4-838d-0cba532b6737,LBGroup: [],Host: 192.168.122.21,Port: 8259,Type: ajp,flushpackets: 0,flushwait: 10,ping: 10,smax: 1,ttl: 60,timeout: 0

      host: 1 [site01] vhost: 1 node: 1

      host: 2 [site01alias01] vhost: 1 node: 1

      host: 3 [site02] vhost: 2 node: 1

      context: 1 [/context01] vhost: 1 node: 1 status: 1

      context: 2 [/context02] vhost: 2 node: 1 status: 1

       

       

      On REMOVE:

       

      balancer: [1] Name: balancer01 Sticky: 1 [JSESSIONID]/[jsessionid] remove: 0 force: 0 Timeout: 0 maxAttempts: 1

      node: [1:1],Balancer: balancer01,JVMRoute: bf3c1d57-ed66-38b4-838d-0cba532b6737,LBGroup: [],Host: 192.168.122.21,Port: 8259,Type: ajp,flushpackets: 0,flushwait: 10,ping: 10,smax: 1,ttl: 60,timeout: 0

      host: 2 [site01alias01] vhost: 1 node: 1

      host: 3 [site02] vhost: 2 node: 1

      context: 2 [/context02] vhost: 2 node: 1 status: 1

       

       

      To fix this, always inside process_appl_cmd I noticed that it was removing only the first host. So I modified it to remove all the hosts of that node with that vhost id.

       

      @@ -1400,7 +1400,16 @@

               }

               if (i==size) {

                   hostinfo.id = host->id;

      -            remove_host(hoststatsmem, &hostinfo);

      +

      +            size = get_ids_used_host(hoststatsmem, id);

      +            for (i=0; i<size; i++) {

      +                 hostinfo_t *ou;

      +

      +                 if (get_host(hoststatsmem, &ou, id[i]) != APR_SUCCESS)

      +                     continue;

      +                 if(ou->vhost == host->vhost && ou->node == node->mess.id)

      +                     remove_host(hoststatsmem, ou);

      +            }

               }

           } else if (status == STOPPED) {

               /* insert_update_contexts in fact makes that vhost->context corresponds only to the first context... */

       

       

       

       

      Assuming my analysis (and patches) are correct I've got a couple of related questions:

       

      *) Aren't there some concurrency problems if multiple concurrent MCMP command are coming (we get the ids using get_ids_used_host and then call of every id get_host with the risk that something can be added in the meantime?)

       

      *) Looking at the code I noticed that inside a CONFIG command some optional Alias and Contexts options can be added and looks like the logic inside process_config should create multiple vhosts.

      But there's something strange in the implementation. The variable phost at line 1007 is resetted to vhost (that has its field to NULL) just before using it (and vhost isn't used before):

       

       

       

      ...

          /* Insert the Alias and corresponding Context */

          phost = vhost

      ...

       

       

      At least in my tests, jboss as 7.1 doesn't sends these options so I haven't tested it.

        • 1. Re: mod_manager and multiple virtualhosts per node
          jfclere

          It looks like you find a bug and have a fix. Please open a JIRA.

          *) Probably but too many locks are bad for the performances.

          *) CONFIG with optional Alias and Context shoud be removed from the code: the JAVA part never uses that.

          • 2. Re: mod_manager and multiple virtualhosts per node
            simone.gotti

            Thanks Jean,

             

            I opend this JIRA with (I hope) a better patch (fixed some missing initializations): https://issues.jboss.org/browse/MODCLUSTER-311

             

            Despite of the comment I put in the patch, thinking more about the possibile race conditions in mod_manager, probably they can happen in various other places (for example if between the calls to "int size = loc_get_max_size_host(); int *id = apr_palloc(r->pool, sizeof(int) * size);" and size = get_ids_used_host(hoststatsmem, id); another process/thread adds/removes something from the table).

            As the calls to mod_manager are not so many maybe some locking could avoid these very rare but possible race conditions...

            • 3. Re: mod_manager and multiple virtualhosts per node
              jfclere

              Thanks for the JIRA.

               

              In fact a part the balancers (I fixed the problem yesterday) there shouldn't be race condition: the node can only send one message at a time and it waits for the answer.