Clúster JGroups independiente para cada Server Group en Jboss EAP 6.x+ modo dominio

By | May 9, 2018

Si utilizamos Jboss en modo dominio seguramente tengamos aplicaciones agrupadas en distintos Server Groups. Éstos a su vez estarán asociados a un Profile en concreto. En caso de ser HA podría ser:

<server-groups>
    <server-group name="server-group-1" profile="ha">                                                                                                                                                     
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
    </server-group>
    <server-group name="server-group-2" profile="full-ha">
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="full-ha-sockets"/>
    </server-group>
</server-groups>

Si cada Server Group utiliza un Profile de forma dedicada -como vemos anteriormente- no tendremos problema alguno. Configuraremos el subsistema JGroups tal y como deseemos en cada caso y no habrá conflicto. Ahora bien, puede darse el caso de que queramos reutilizar un mismo Profile para varios Server Groups:

<server-groups>
    <server-group name="server-group-1" profile="ha">                                                                                                                                                     
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
    </server-group>
    <server-group name="server-group-2" profile="ha">
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
    </server-group>
</server-groups>

Como vemos ambos grupos utilizan el mismo profile HA y por defecto compartirían clúster todos los nodos, aunque fueran de distinto Server Group.. Podemos no obstante crear un clúster independiente para cada Server Group. Según sea UDP o TCPPING procederemos de distinta manera.

Clúster UDP

Si el clúster es por UDP tendremos un stack como el siguiente:

<stack name="udp">
    <transport type="UDP" socket-binding="jgroups-udp"/>
    <protocol type="PING"/>
    <protocol type="MERGE3"/>
    <protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
    <protocol type="FD_ALL"/>
    <protocol type="VERIFY_SUSPECT"/>
    <protocol type="pbcast.NAKACK2"/>
    <protocol type="UNICAST3"/>
    <protocol type="pbcast.STABLE"/>
    <protocol type="pbcast.GMS"/>
    <protocol type="UFC"/>
    <protocol type="MFC"/>
    <protocol type="FRAG2"/>
</stack>

La capa de transporte utiliza el binding jgroups-udp para definir la IP multicast por defecto (230.0.0.4)

<socket-binding-group name="ha-sockets" default-interface="public">
    <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
    <socket-binding name="http" port="${jboss.http.port:8080}"/>
    <socket-binding name="https" port="${jboss.https.port:8443}"/>
    <socket-binding name="jgroups-mping" interface="private" port="0" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45700"/>
    <socket-binding name="jgroups-tcp" interface="private" port="7600"/>
    <socket-binding name="jgroups-tcp-fd" interface="private" port="57600"/>
    <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45688"/>                                          
    <socket-binding name="jgroups-udp-fd" interface="private" port="54200"/>
    <socket-binding name="modcluster" port="0" multicast-address="224.0.1.105" multicast-port="23364"/>
    <socket-binding name="txn-recovery-environment" port="4712"/>
    <socket-binding name="txn-status-manager" port="4713"/>
    <outbound-socket-binding name="mail-smtp">
        <remote-destination host="localhost" port="25"/>
    </outbound-socket-binding>
</socket-binding-group>

Podemos crear una propiedad de sistema en cada Server Group para que cada uno utilice una IP multicast distinta:

<server-groups>
    <server-group name="server-group-1" profile="ha">                                                                                                                                                     
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jboss.default.multicast.address" value="230.0.0.5" />
        </system-properties>
    </server-group>
    <server-group name="server-group-2" profile="ha">
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jboss.default.multicast.address" value="230.0.0.6" />
        </system-properties>
    </server-group>
</server-groups>

Clúster TCPPING

Imaginemos que las instancias 192.168.2.101 y 192.168.2.102 son del server-group-1 mientras que 192.168.2.103 y 192.168.2.104 son del server-group-2 En este caso tendremos un stack similar a:

<stack name="tcp">
     <transport type="TCP" socket-binding="jgroups-tcp"/>
     <protocol type="TCPPING">
           <property name="initial_hosts">192.168.2.101[7600],192.168.2.102[7600],192.168.2.103[7600],192.168.2.104[7600]</property>
           <property name="port_range">0</property>
     </protocol>
     <protocol type="MERGE3"/>
     <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
     <protocol type="FD"/>
     <protocol type="VERIFY_SUSPECT"/>
     <protocol type="pbcast.NAKACK2"/>
     <protocol type="UNICAST3"/>
     <protocol type="pbcast.STABLE"/>
     <protocol type="pbcast.GMS"/>
     <protocol type="MFC"/>
     <protocol type="FRAG2"/>
</stack>

La solución pasaría por crear una variable en dicho stack para poder realizar la definición a nivel de Server Group de los hosts que forman parte del clúster. En este ejemplo la llamaremos ${jgroups.initial.hosts}

<stack name="tcp">
     <transport type="TCP" socket-binding="jgroups-tcp"/>
     <protocol type="TCPPING">
           <property name="initial_hosts">${jgroups.initial.hosts}</property>
           <property name="port_range">0</property>
     </protocol>
     <protocol type="MERGE3"/>
     <protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
     <protocol type="FD"/>
     <protocol type="VERIFY_SUSPECT"/>
     <protocol type="pbcast.NAKACK2"/>
     <protocol type="UNICAST3"/>
     <protocol type="pbcast.STABLE"/>
     <protocol type="pbcast.GMS"/>
     <protocol type="MFC"/>
     <protocol type="FRAG2"/>
</stack>

Ahora en la definición de los Server Groups creamos la variable correspondiente como hicimos en el caso del clúster UDP:

<server-groups>
    <server-group name="server-group-1" profile="ha">                                                                                                                                                     
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jgroups.initial.hosts" value="192.168.2.101[7600],192.168.2.102[7600]" />
        </system-properties>
    </server-group>
    <server-group name="server-group-2" profile="ha">
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jgroups.initial.hosts" value="192.168.2.103[7600],192.168.2.104[7600]" />
        </system-properties>
    </server-group>
</server-groups>

Si las instancias de cada Server Group utilizan la misma IP, tener en cuenta los offsets de puertos, por ejemplo:

<server-groups>
    <server-group name="server-group-1" profile="ha">                                                                                                                                                     
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jgroups.initial.hosts" value="192.168.2.101[7600],192.168.2.101[7700]" />
        </system-properties>
    </server-group>
    <server-group name="server-group-2" profile="ha">
        <jvm name="default">
            <heap size="1000m" max-size="1000m"/>
        </jvm>
        <socket-binding-group ref="ha-sockets"/>
        <system-properties>
          <property name="jgroups.initial.hosts" value="192.168.2.101[7800],192.168.2.101[7900]" />
        </system-properties>
    </server-group>
</server-groups>

😉