WildFly HornetQ-Based Messaging Subsystem - Clustering with TCP

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

External

Internal

Relevance

  • EAP 6.4

Overview

This article shows how to configure a network of HornetQ brokers, assuming that the network has no multicast capabilities. For more details on HornetQ Clustering see WildFly HornetQ Clustering Concepts.

Procedure

Make Sure <clustering> is Enabled

The "messaging" subsystem must be configured with <clustered>true</clustered> on all nodes of the cluster:

<subsystem xmlns="urn:jboss:domain:messaging:1.4">
   <hornetq-server>
      ... 
      <clustered>true</clustered>
      ...
</subsystem>

<clustered> post EAP 6.1

Starting with EAP 6.1, the <clustered> configuration attribute was deprecated. If specified, the following message shows up in the logs:

11:52:05,484 WARN  [org.jboss.as.messaging] (Controller Boot Thread) JBAS011608: Element CLUSTERED is deprecated and will not be taken into account

Messaging clustering is enabled if one or more <cluster-connection> elements are defined. For more details about <cluster-connection> see Add a <cluster-connection> section.

On Each Cluster Node Configure Connectors To All Other Nodes

Assuming the cluster has three nodes ("node1", "node2" and "node3"), the configuration for node1 should declare <connector>s and <outbound-socket-binding>s for node2 and node3:

   ...
   <subsystem xmlns="urn:jboss:domain:messaging:1.4">
      <hornetq-server>
         ...
         <connectors>
            ...
            <netty-connector name="node2-connector" socket-binding="node2-hornetq-binding"/>
            <netty-connector name="node3-connector" socket-binding="node3-hornetq-binding"/>
         </connectors>
         ...
   </subsystem>
   ...
    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
        ...
        <outbound-socket-binding name="node2-hornetq-binding">
            <remote-destination host="1.2.3.5" port="5445"/>
        </outbound-socket-binding>
        <outbound-socket-binding name="node3-hornetq-binding">
            <remote-destination host="1.2.3.6" port="5445"/>
        </outbound-socket-binding>
    </socket-binding-group>
   ...

Note: make sure the nodes at the other end of the connection actually listen on the specified interfaces/ports.

Comment out <broadcast-groups>, <discovery-groups>

They are useless without multicast.

Add a <cluster-connection>

Cluster connections are unidirectiona and point-to-point. Only one initiator node and one target node can participate to a cluster connection, so for this reason, only one connector-ref can be added as a static-connector for a cluster connection. If connections to more than one nodes are needed, add more <cluster-connection>s.
   ...
   </address-settings>

   <cluster-connections>

      <cluster-connection name="tcp-based-cluster-node1-to-node2">
         <address>jms</address>
         <connector-ref>netty</connector-ref>
         <retry-interval>500</retry-interval>
         <use-duplicate-detection>true</use-duplicate-detection>
         <forward-when-no-consumers>true</forward-when-no-consumers>
         <max-hops>1</max-hops>
         <static-connectors>
           <!-- just one connector-ref here -->
           <connector-ref>node2-connector</connector-ref>
          </static-connectors>
       </cluster-connection>

      <cluster-connection name="tcp-based-cluster-node1-to-node3">
         <address>jms</address>
         <connector-ref>netty</connector-ref>
         <retry-interval>500</retry-interval>
         <use-duplicate-detection>true</use-duplicate-detection>
         <forward-when-no-consumers>true</forward-when-no-consumers>
         <max-hops>1</max-hops>
         <static-connectors>
           <!-- just one connector-ref here -->
           <connector-ref>node3-connector</connector-ref>
          </static-connectors>
       </cluster-connection>

   </cluster-connections>
   ...

In EAP 6.1 or newer, adding a <cluster-connection> makes the <clustered> configuration element redundant.

Configure Security

If security is enabled (the <securit-enabled> configuration element is "true", and this is the default value even if it is not explicitly declared), then connections authenticate themselves as "HORNETQ.CLUSTER.ADMIN.USER" - the "cluster user". Unless a "cluster password" is specified in the configuration, a random password is used, and the connection establishing will fail. In order to provide known credentials for the cluster connections, configure the following (<cluster-user> is optional and if not specified will default to "HORNETQ.CLUSTER.ADMIN.USER"):

...
<subsystem xmlns="urn:jboss:domain:messaging:1.4">
   <hornetq-server>
      ...
      <cluster-user>hq</cluster-user>
      <cluster-password>hq123</cluster-password>
      ...
   </hornetq-server>
</subsystem>
...      

The user declared as such does not need to be declared in any security repository, the configuration file declaration is sufficient.

Confirmation

You should see this in the logs:

EAP 6.4

20:37:47,719 INFO  [org.hornetq.core.server] (Thread-16 (HornetQ-server-HornetQServerImpl::serverUUID=5032e902-e3fe-11e5-926c-a50d5e1d9a16-46422202)) HQ221027: Bridge ClusterConnectionBridge@20600d51 [name=sf.tcp-based-cluster.c9e7d432-e3fe-11e5-915f-d3dc1740ef3d, queue=QueueImpl[name=sf.tcp-based-cluster.c9e7d432-e3fe-11e5-915f-d3dc1740ef3d, postOffice=PostOfficeImpl [server=HornetQServerImpl::serverUUID=5032e902-e3fe-11e5-926c-a50d5e1d9a16]]@298aa2ce targetConnector=ServerLocatorImpl (identity=(Cluster-connection-bridge::ClusterConnectionBridge@20600d51 [name=sf.tcp-based-cluster.c9e7d432-e3fe-11e5-915f-d3dc1740ef3d, queue=QueueImpl[name=sf.tcp-based-cluster.c9e7d432-e3fe-11e5-915f-d3dc1740ef3d, postOffice=PostOfficeImpl [server=HornetQServerImpl::serverUUID=5032e902-e3fe-11e5-926c-a50d5e1d9a16]]@298aa2ce targetConnector=ServerLocatorImpl [initialConnectors=[TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory) ?port=5445&host=172-31-17-79], discoveryGroupConfiguration=null]]::ClusterConnectionImpl@1116810330[nodeUUID=5032e902-e3fe-11e5-926c-a50d5e1d9a16, connector=TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory) ?port=5445&host=172-31-28-2, address=jms, server=HornetQServerImpl::serverUUID=5032e902-e3fe-11e5-926c-a50d5e1d9a16])) [initialConnectors=[TransportConfiguration(name=netty, factory=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory) ?port=5445&host=172-31-17-79], discoveryGroupConfiguration=null]] is connected

Other

15:11:19,234 INFO  [org.hornetq.core.server.cluster.impl.BridgeImpl] (Thread-7 (HornetQ-server-HornetQServerImpl::serverUUID=388611e3-810b-11e2-85c9-694bd06e7c3c-544291442)) Bridge ClusterConnectionBridge@26250f55 [name=sf.o01-o02-tcp-cluster.c07654e0-810b-11e2-a372-f9f6868e86f7, queue=QueueImpl[name=sf.o01-o02-tcp-cluster.c07654e0-810b-11e2-a372-f9f6868e86f7, postOffice=PostOfficeImpl [server=HornetQServerImpl::serverUUID=388611e3-810b-11e2-85c9-694bd06e7c3c]]@4b11a903 targetConnector=ServerLocatorImpl (identity=(Cluster-connection-bridge::ClusterConnectionBridge@26250f55 [name=sf.o01-o02-tcp-cluster.c07654e0-810b-11e2-a372-f9f6868e86f7, queue=QueueImpl[name=sf.o01-o02-tcp-cluster.c07654e0-810b-11e2-a372-f9f6868e86f7, postOffice=PostOfficeImpl [server=HornetQServerImpl::serverUUID=388611e3-810b-11e2-85c9-694bd06e7c3c]]@4b11a903 targetConnector=ServerLocatorImpl [initialConnectors=[org-hornetq-core-remoting-impl-netty-NettyConnectorFactory?port=5445&host=10-76-128-155], discoveryGroupConfiguration=null]]::ClusterConnectionImpl@1267429957[nodeUUID=388611e3-810b-11e2-85c9-694bd06e7c3c, connector=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory?port=5445&host=10-76-128-154, address=jms, server=HornetQServerImpl::serverUUID=388611e3-810b-11e2-85c9-694bd06e7c3c])) [initialConnectors=[org-hornetq-core-remoting-impl-netty-NettyConnectorFactory?port=5445&host=10-76-128-155], discoveryGroupConfiguration=null]] is connected

Configure ConnectionFactory for Load Balancing

Add the extra connectors to each ConnectionFactories that are exposed and supposed to be used for load balancing/failover. The connectors are the same that have been added to the cluster connection <static-connectors> list:

...
<subsystem xmlns="urn:jboss:domain:messaging:1.4">
   <hornetq-server>
      ...
      <jms-connection-factories>
         ...
         <connection-factory name="RemoteConnectionFactory">
            <connectors>
               <connector-ref connector-name="netty"/>
               <connector-ref connector-name="node2-connector"/>
               <connector-ref connector-name="node3-connector"/>
            </connectors>
            <entries>
               <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
            </entries>

             <!--
                 Optionally:
             -->
             <connection-load-balancing-policy-class-name>
                 org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy
             </connection-load-balancing-policy-class-name>
         </connection-factory>
         ...
      </jms-connection-factories>
   </hornetq-server>
 </subsystem>
...

For more details on load balancing, see:

Client-Side Load Balancing

What Happens if a Cluster Node is Down when Other Starts Up

The node that is starting up attempts to connect ? times.

If it can't, it logs as DEBUG:

2013-02-20 11:39:45,131 DEBUG [org.hornetq.core.client.impl.ServerLocatorImpl] (Thread-1 (HornetQ-server-HornetQServerImpl::serverUUID=afe53124-6e53-11e2-bb90-005056ac34a6-1045936331)) Connector [initialConnector=org-hornetq-core-remoting-impl-netty-NettyConnectorFactory?port=5445&host=10-153-198-31]::Exception on establish connector initial connection
HornetQException[errorCode=2 message=Unable to connect to server using configuration org-hornetq-core-remoting-impl-netty-NettyConnectorFactory?port=5445&host=10-153-198-31]
        at org.hornetq.core.client.impl.ClientSessionFactoryImpl.connect(ClientSessionFactoryImpl.java:233)
        at org.hornetq.core.client.impl.ServerLocatorImpl$StaticConnector$Connector.tryConnect(ServerLocatorImpl.java:1787)
        at org.hornetq.core.client.impl.ServerLocatorImpl$StaticConnector.connect(ServerLocatorImpl.java:1624)
        at org.hornetq.core.client.impl.ServerLocatorImpl.connect(ServerLocatorImpl.java:597)
        at org.hornetq.core.client.impl.ServerLocatorImpl$3.run(ServerLocatorImpl.java:564)
        at org.hornetq.utils.OrderedExecutorFactory$OrderedExecutor$1.run(OrderedExecutorFactory.java:100)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)

Client-Side

Messaging Concepts - Client-Side Load Balancing