blob: 2dae872fd075fceea117e1d4900c5322db0a3352 [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="" >
<head>
<title>Clusters ยท ActiveMQ Artemis Documentation</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="generator" content="GitBook 3.1.1">
<link rel="stylesheet" href="gitbook/style.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
<link rel="next" href="federation.html" />
<link rel="prev" href="duplicate-detection.html" />
</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>
<nav role="navigation">
<ul class="summary">
<li class="chapter " data-level="1.1" data-path="./">
<a href="./">
Introduction
</a>
</li>
<li class="chapter " data-level="1.2" data-path="notice.html">
<a href="notice.html">
Legal Notice
</a>
</li>
<li class="chapter " data-level="1.3" data-path="preface.html">
<a href="preface.html">
Preface
</a>
</li>
<li class="chapter " data-level="1.4" data-path="project-info.html">
<a href="project-info.html">
Project Info
</a>
</li>
<li class="chapter " data-level="1.5" data-path="versions.html">
<a href="versions.html">
Versions
</a>
</li>
<li class="chapter " data-level="1.6" data-path="messaging-concepts.html">
<a href="messaging-concepts.html">
Messaging Concepts
</a>
</li>
<li class="chapter " data-level="1.7" data-path="architecture.html">
<a href="architecture.html">
Architecture
</a>
</li>
<li class="chapter " data-level="1.8" data-path="using-server.html">
<a href="using-server.html">
Using the Server
</a>
</li>
<li class="chapter " data-level="1.9" data-path="upgrading.html">
<a href="upgrading.html">
Upgrading
</a>
</li>
<li class="chapter " data-level="1.10" data-path="address-model.html">
<a href="address-model.html">
Address Model
</a>
</li>
<li class="chapter " data-level="1.11" data-path="protocols-interoperability.html">
<a href="protocols-interoperability.html">
Protocols and Interoperability
</a>
</li>
<li class="chapter " data-level="1.12" data-path="amqp.html">
<a href="amqp.html">
AMQP
</a>
</li>
<li class="chapter " data-level="1.13" data-path="mqtt.html">
<a href="mqtt.html">
MQTT
</a>
</li>
<li class="chapter " data-level="1.14" data-path="stomp.html">
<a href="stomp.html">
STOMP
</a>
</li>
<li class="chapter " data-level="1.15" data-path="openwire.html">
<a href="openwire.html">
OpenWire
</a>
</li>
<li class="chapter " data-level="1.16" data-path="core.html">
<a href="core.html">
Core
</a>
</li>
<li class="chapter " data-level="1.17" data-path="jms-core-mapping.html">
<a href="jms-core-mapping.html">
Mapping JMS Concepts to the Core API
</a>
</li>
<li class="chapter " data-level="1.18" data-path="using-jms.html">
<a href="using-jms.html">
Using JMS
</a>
</li>
<li class="chapter " data-level="1.19" data-path="client-classpath.html">
<a href="client-classpath.html">
The Client Classpath
</a>
</li>
<li class="chapter " data-level="1.20" data-path="examples.html">
<a href="examples.html">
Examples
</a>
</li>
<li class="chapter " data-level="1.21" data-path="wildcard-routing.html">
<a href="wildcard-routing.html">
Routing Messages With Wild Cards
</a>
</li>
<li class="chapter " data-level="1.22" data-path="wildcard-syntax.html">
<a href="wildcard-syntax.html">
Wildcard Syntax
</a>
</li>
<li class="chapter " data-level="1.23" data-path="filter-expressions.html">
<a href="filter-expressions.html">
Filter Expressions
</a>
</li>
<li class="chapter " data-level="1.24" data-path="persistence.html">
<a href="persistence.html">
Persistence
</a>
</li>
<li class="chapter " data-level="1.25" data-path="configuring-transports.html">
<a href="configuring-transports.html">
Configuring Transports
</a>
</li>
<li class="chapter " data-level="1.26" data-path="config-reload.html">
<a href="config-reload.html">
Configuration Reload
</a>
</li>
<li class="chapter " data-level="1.27" data-path="connection-ttl.html">
<a href="connection-ttl.html">
Detecting Dead Connections
</a>
</li>
<li class="chapter " data-level="1.28" data-path="slow-consumers.html">
<a href="slow-consumers.html">
Detecting Slow Consumers
</a>
</li>
<li class="chapter " data-level="1.29" data-path="network-isolation.html">
<a href="network-isolation.html">
Avoiding Network Isolation
</a>
</li>
<li class="chapter " data-level="1.30" data-path="critical-analysis.html">
<a href="critical-analysis.html">
Detecting Broker Issues (Critical Analysis)
</a>
</li>
<li class="chapter " data-level="1.31" data-path="transaction-config.html">
<a href="transaction-config.html">
Resource Manager Configuration
</a>
</li>
<li class="chapter " data-level="1.32" data-path="flow-control.html">
<a href="flow-control.html">
Flow Control
</a>
</li>
<li class="chapter " data-level="1.33" data-path="send-guarantees.html">
<a href="send-guarantees.html">
Guarantees of sends and commits
</a>
</li>
<li class="chapter " data-level="1.34" data-path="undelivered-messages.html">
<a href="undelivered-messages.html">
Message Redelivery and Undelivered Messages
</a>
</li>
<li class="chapter " data-level="1.35" data-path="message-expiry.html">
<a href="message-expiry.html">
Message Expiry
</a>
</li>
<li class="chapter " data-level="1.36" data-path="large-messages.html">
<a href="large-messages.html">
Large Messages
</a>
</li>
<li class="chapter " data-level="1.37" data-path="paging.html">
<a href="paging.html">
Paging
</a>
</li>
<li class="chapter " data-level="1.38" data-path="scheduled-messages.html">
<a href="scheduled-messages.html">
Scheduled Messages
</a>
</li>
<li class="chapter " data-level="1.39" data-path="last-value-queues.html">
<a href="last-value-queues.html">
Last-Value Queues
</a>
</li>
<li class="chapter " data-level="1.40" data-path="ring-queues.html">
<a href="ring-queues.html">
Ring Queues
</a>
</li>
<li class="chapter " data-level="1.41" data-path="retroactive-addresses.html">
<a href="retroactive-addresses.html">
Retroactive Addresses
</a>
</li>
<li class="chapter " data-level="1.42" data-path="exclusive-queues.html">
<a href="exclusive-queues.html">
Exclusive Queues
</a>
</li>
<li class="chapter " data-level="1.43" data-path="message-grouping.html">
<a href="message-grouping.html">
Message Grouping
</a>
</li>
<li class="chapter " data-level="1.44" data-path="consumer-priority.html">
<a href="consumer-priority.html">
Consumer Priority
</a>
</li>
<li class="chapter " data-level="1.45" data-path="pre-acknowledge.html">
<a href="pre-acknowledge.html">
Extra Acknowledge Modes
</a>
</li>
<li class="chapter " data-level="1.46" data-path="management.html">
<a href="management.html">
Management
</a>
</li>
<li class="chapter " data-level="1.47" data-path="management-console.html">
<a href="management-console.html">
Management Console
</a>
</li>
<li class="chapter " data-level="1.48" data-path="metrics.html">
<a href="metrics.html">
Metrics
</a>
</li>
<li class="chapter " data-level="1.49" data-path="security.html">
<a href="security.html">
Security
</a>
</li>
<li class="chapter " data-level="1.50" data-path="masking-passwords.html">
<a href="masking-passwords.html">
Masking Passwords
</a>
</li>
<li class="chapter " data-level="1.51" data-path="broker-plugins.html">
<a href="broker-plugins.html">
Broker Plugins
</a>
</li>
<li class="chapter " data-level="1.52" data-path="resource-limits.html">
<a href="resource-limits.html">
Resource Limits
</a>
</li>
<li class="chapter " data-level="1.53" data-path="jms-bridge.html">
<a href="jms-bridge.html">
The JMS Bridge
</a>
</li>
<li class="chapter " data-level="1.54" data-path="client-reconnection.html">
<a href="client-reconnection.html">
Client Reconnection and Session Reattachment
</a>
</li>
<li class="chapter " data-level="1.55" data-path="diverts.html">
<a href="diverts.html">
Diverting and Splitting Message Flows
</a>
</li>
<li class="chapter " data-level="1.56" data-path="core-bridges.html">
<a href="core-bridges.html">
Core Bridges
</a>
</li>
<li class="chapter " data-level="1.57" data-path="transformers.html">
<a href="transformers.html">
Transformers
</a>
</li>
<li class="chapter " data-level="1.58" data-path="duplicate-detection.html">
<a href="duplicate-detection.html">
Duplicate Message Detection
</a>
</li>
<li class="chapter active" data-level="1.59" data-path="clusters.html">
<a href="clusters.html">
Clusters
</a>
</li>
<li class="chapter " data-level="1.60" data-path="federation.html">
<a href="federation.html">
Federation
</a>
<ul class="articles">
<li class="chapter " data-level="1.60.1" data-path="federation-address.html">
<a href="federation-address.html">
Address Federation
</a>
</li>
<li class="chapter " data-level="1.60.2" data-path="federation-queue.html">
<a href="federation-queue.html">
Queue Federation
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.61" data-path="ha.html">
<a href="ha.html">
High Availability and Failover
</a>
</li>
<li class="chapter " data-level="1.62" data-path="graceful-shutdown.html">
<a href="graceful-shutdown.html">
Graceful Server Shutdown
</a>
</li>
<li class="chapter " data-level="1.63" data-path="libaio.html">
<a href="libaio.html">
Libaio Native Libraries
</a>
</li>
<li class="chapter " data-level="1.64" data-path="thread-pooling.html">
<a href="thread-pooling.html">
Thread management
</a>
</li>
<li class="chapter " data-level="1.65" data-path="web-server.html">
<a href="web-server.html">
Embedded Web Server
</a>
</li>
<li class="chapter " data-level="1.66" data-path="logging.html">
<a href="logging.html">
Logging
</a>
</li>
<li class="chapter " data-level="1.67" data-path="rest.html">
<a href="rest.html">
REST Interface
</a>
</li>
<li class="chapter " data-level="1.68" data-path="embedding-activemq.html">
<a href="embedding-activemq.html">
Embedding the Broker
</a>
</li>
<li class="chapter " data-level="1.69" data-path="karaf.html">
<a href="karaf.html">
Apache Karaf
</a>
</li>
<li class="chapter " data-level="1.70" data-path="tomcat.html">
<a href="tomcat.html">
Apache Tomcat
</a>
</li>
<li class="chapter " data-level="1.71" data-path="spring-integration.html">
<a href="spring-integration.html">
Spring Integration
</a>
</li>
<li class="chapter " data-level="1.72" data-path="cdi-integration.html">
<a href="cdi-integration.html">
CDI Integration
</a>
</li>
<li class="chapter " data-level="1.73" data-path="intercepting-operations.html">
<a href="intercepting-operations.html">
Intercepting Operations
</a>
</li>
<li class="chapter " data-level="1.74" data-path="data-tools.html">
<a href="data-tools.html">
Data Tools
</a>
</li>
<li class="chapter " data-level="1.75" data-path="maven-plugin.html">
<a href="maven-plugin.html">
Maven Plugin
</a>
</li>
<li class="chapter " data-level="1.76" data-path="unit-testing.html">
<a href="unit-testing.html">
Unit Testing
</a>
</li>
<li class="chapter " data-level="1.77" data-path="perf-tuning.html">
<a href="perf-tuning.html">
Troubleshooting and Performance Tuning
</a>
</li>
<li class="chapter " data-level="1.78" data-path="configuration-index.html">
<a href="configuration-index.html">
Configuration Reference
</a>
</li>
<li class="divider"></li>
<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href="." >Clusters</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h1 id="clusters">Clusters</h1>
<h2 id="overview">Overview</h2>
<p>Apache ActiveMQ Artemis clusters allow groups of Apache ActiveMQ Artemis servers to be grouped
together in order to share message processing load. Each active node in
the cluster is an active Apache ActiveMQ Artemis server which manages its own messages
and handles its own connections.</p>
<p>The cluster is formed by each node declaring <em>cluster connections</em> to
other nodes in the core configuration file <code>broker.xml</code>.
When a node forms a cluster connection to another node, internally it
creates a <em>core bridge</em> (as described in <a href="core-bridges.html">Core Bridges</a>) connection between it and
the other node, this is done transparently behind the scenes - you don&apos;t
have to declare an explicit bridge for each node. These cluster
connections allow messages to flow between the nodes of the cluster to
balance load.</p>
<p>Nodes can be connected together to form a cluster in many different
topologies, we will discuss a couple of the more common topologies later
in this chapter.</p>
<p>We&apos;ll also discuss client side load balancing, where we can balance
client connections across the nodes of the cluster, and we&apos;ll consider
message redistribution where Apache ActiveMQ Artemis will redistribute messages between
nodes to avoid starvation.</p>
<p>Another important part of clustering is <em>server discovery</em> where servers
can broadcast their connection details so clients or other servers can
connect to them with the minimum of configuration.</p>
<blockquote>
<p><a id="copy-warning"></a><strong>Warning</strong></p>
<p>Once a cluster node has been configured it is common to simply copy
that configuration to other nodes to produce a symmetric cluster.
However, care must be taken when copying the Apache ActiveMQ Artemis files. Do not
copy the Apache ActiveMQ Artemis <em>data</em> (i.e. the <code>bindings</code>, <code>journal</code>, and
<code>large-messages</code> directories) from one node to another. When a node is
started for the first time and initializes its journal files it also
persists a special identifier to the <code>journal</code> directory. This id
<em>must</em> be unique among nodes in the cluster or the cluster will not
form properly.</p>
</blockquote>
<h2 id="server-discovery">Server discovery</h2>
<p>Server discovery is a mechanism by which servers can propagate their
connection details to:</p>
<ul>
<li><p>Messaging clients. A messaging client wants to be able to connect to
the servers of the cluster without having specific knowledge of
which servers in the cluster are up at any one time.</p>
</li>
<li><p>Other servers. Servers in a cluster want to be able to create
cluster connections to each other without having prior knowledge of
all the other servers in the cluster.</p>
</li>
</ul>
<p>This information, let&apos;s call it the Cluster Topology, is actually sent
around normal Apache ActiveMQ Artemis connections to clients and to other servers over
cluster connections. This being the case we need a way of establishing
the initial first connection. This can be done using dynamic discovery
techniques like
<a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol" target="_blank">UDP</a> and
<a href="http://www.jgroups.org/" target="_blank">JGroups</a>, or by providing a list of initial
connectors.</p>
<h3 id="dynamic-discovery">Dynamic Discovery</h3>
<p>Server discovery uses
<a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol" target="_blank">UDP</a> multicast or
<a href="http://www.jgroups.org/" target="_blank">JGroups</a> to broadcast server connection
settings.</p>
<h4 id="broadcast-groups">Broadcast Groups</h4>
<p>A broadcast group is the means by which a server broadcasts connectors
over the network. A connector defines a way in which a client (or other
server) can make connections to the server. For more information on what
a connector is, please see <a href="configuring-transports.html">Configuring the Transport</a>.</p>
<p>The broadcast group takes a set of connector pairs, each connector pair
contains connection settings for a live and backup server (if one
exists) and broadcasts them on the network. Depending on which
broadcasting technique you configure the cluster, it uses either UDP or
JGroups to broadcast connector pairs information.</p>
<p>Broadcast groups are defined in the server configuration file
<code>broker.xml</code>. There can be many broadcast groups per
Apache ActiveMQ Artemis server. All broadcast groups must be defined in a
<code>broadcast-groups</code> element.</p>
<p>Let&apos;s take a look at an example broadcast group from
<code>broker.xml</code> that defines a UDP broadcast group:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">broadcast-groups</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">broadcast-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-broadcast-group&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">local-bind-address</span>&gt;</span>172.16.9.3<span class="hljs-tag">&lt;/<span class="hljs-name">local-bind-address</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">local-bind-port</span>&gt;</span>5432<span class="hljs-tag">&lt;/<span class="hljs-name">local-bind-port</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">group-address</span>&gt;</span>231.7.7.7<span class="hljs-tag">&lt;/<span class="hljs-name">group-address</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">group-port</span>&gt;</span>9876<span class="hljs-tag">&lt;/<span class="hljs-name">group-port</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">broadcast-period</span>&gt;</span>2000<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-period</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>netty-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-groups</span>&gt;</span>
</code></pre>
<p>Some of the broadcast group parameters are optional and you&apos;ll normally
use the defaults, but we specify them all in the above example for
clarity. Let&apos;s discuss each one in turn:</p>
<ul>
<li><p><code>name</code> attribute. Each broadcast group in the server must have a
unique name.</p>
</li>
<li><p><code>local-bind-address</code>. This is the local bind address that the
datagram socket is bound to. If you have multiple network interfaces
on your server, you would specify which one you wish to use for
broadcasts by setting this property. If this property is not
specified then the socket will be bound to the wildcard address, an
IP address chosen by the kernel. This is a UDP specific attribute.</p>
</li>
<li><p><code>local-bind-port</code>. If you want to specify a local port to which the
datagram socket is bound you can specify it here. Normally you would
just use the default value of <code>-1</code> which signifies that an anonymous
port should be used. This parameter is always specified in
conjunction with <code>local-bind-address</code>. This is a UDP specific
attribute.</p>
</li>
<li><p><code>group-address</code>. This is the multicast address to which the data
will be broadcast. It is a class D IP address in the range
<code>224.0.0.0</code> to <code>239.255.255.255</code>, inclusive. The address <code>224.0.0.0</code>
is reserved and is not available for use. This parameter is
mandatory. This is a UDP specific attribute.</p>
</li>
<li><p><code>group-port</code>. This is the UDP port number used for broadcasting.
This parameter is mandatory. This is a UDP specific attribute.</p>
</li>
<li><p><code>broadcast-period</code>. This is the period in milliseconds between
consecutive broadcasts. This parameter is optional, the default
value is <code>2000</code> milliseconds.</p>
</li>
<li><p><code>connector-ref</code>. This specifies the connector and optional backup
connector that will be broadcasted (see <a href="configuring-transports.html">Configuring the Transport</a> for more information on
connectors). </p>
</li>
</ul>
<p>Here is another example broadcast group that defines a JGroups broadcast
group:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">broadcast-groups</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">broadcast-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-broadcast-group&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">jgroups-file</span>&gt;</span>test-jgroups-file_ping.xml<span class="hljs-tag">&lt;/<span class="hljs-name">jgroups-file</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">jgroups-channel</span>&gt;</span>activemq_broadcast_channel<span class="hljs-tag">&lt;/<span class="hljs-name">jgroups-channel</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">broadcast-period</span>&gt;</span>2000<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-period</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>netty-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">broadcast-groups</span>&gt;</span>
</code></pre>
<p>To be able to use JGroups to broadcast, one must specify two attributes,
i.e. <code>jgroups-file</code> and <code>jgroups-channel</code>, as discussed in details as
following:</p>
<ul>
<li><p><code>jgroups-file</code> attribute. This is the name of JGroups configuration
file. It will be used to initialize JGroups channels. Make sure the
file is in the java resource path so that Apache ActiveMQ Artemis can load it.</p>
</li>
<li><p><code>jgroups-channel</code> attribute. The name that JGroups channels connect
to for broadcasting.</p>
</li>
</ul>
<blockquote>
<p><strong>Note:</strong></p>
<p>The JGroups attributes (<code>jgroups-file</code> and <code>jgroups-channel</code>) and UDP
specific attributes described above are exclusive of each other. Only
one set can be specified in a broadcast group configuration. Don&apos;t mix
them!</p>
</blockquote>
<p>The following is an example of a JGroups file</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">config</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">&quot;urn:org:jgroups&quot;</span>
<span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span>
<span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">&quot;urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.0.xsd&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">TCP</span> <span class="hljs-attr">loopback</span>=<span class="hljs-string">&quot;true&quot;</span>
<span class="hljs-attr">recv_buf_size</span>=<span class="hljs-string">&quot;20000000&quot;</span>
<span class="hljs-attr">send_buf_size</span>=<span class="hljs-string">&quot;640000&quot;</span>
<span class="hljs-attr">discard_incompatible_packets</span>=<span class="hljs-string">&quot;true&quot;</span>
<span class="hljs-attr">max_bundle_size</span>=<span class="hljs-string">&quot;64000&quot;</span>
<span class="hljs-attr">max_bundle_timeout</span>=<span class="hljs-string">&quot;30&quot;</span>
<span class="hljs-attr">enable_bundling</span>=<span class="hljs-string">&quot;true&quot;</span>
<span class="hljs-attr">use_send_queues</span>=<span class="hljs-string">&quot;false&quot;</span>
<span class="hljs-attr">sock_conn_timeout</span>=<span class="hljs-string">&quot;300&quot;</span>
<span class="hljs-attr">thread_pool.enabled</span>=<span class="hljs-string">&quot;true&quot;</span>
<span class="hljs-attr">thread_pool.min_threads</span>=<span class="hljs-string">&quot;1&quot;</span>
<span class="hljs-attr">thread_pool.max_threads</span>=<span class="hljs-string">&quot;10&quot;</span>
<span class="hljs-attr">thread_pool.keep_alive_time</span>=<span class="hljs-string">&quot;5000&quot;</span>
<span class="hljs-attr">thread_pool.queue_enabled</span>=<span class="hljs-string">&quot;false&quot;</span>
<span class="hljs-attr">thread_pool.queue_max_size</span>=<span class="hljs-string">&quot;100&quot;</span>
<span class="hljs-attr">thread_pool.rejection_policy</span>=<span class="hljs-string">&quot;run&quot;</span>
<span class="hljs-attr">oob_thread_pool.enabled</span>=<span class="hljs-string">&quot;true&quot;</span>
<span class="hljs-attr">oob_thread_pool.min_threads</span>=<span class="hljs-string">&quot;1&quot;</span>
<span class="hljs-attr">oob_thread_pool.max_threads</span>=<span class="hljs-string">&quot;8&quot;</span>
<span class="hljs-attr">oob_thread_pool.keep_alive_time</span>=<span class="hljs-string">&quot;5000&quot;</span>
<span class="hljs-attr">oob_thread_pool.queue_enabled</span>=<span class="hljs-string">&quot;false&quot;</span>
<span class="hljs-attr">oob_thread_pool.queue_max_size</span>=<span class="hljs-string">&quot;100&quot;</span>
<span class="hljs-attr">oob_thread_pool.rejection_policy</span>=<span class="hljs-string">&quot;run&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">FILE_PING</span> <span class="hljs-attr">location</span>=<span class="hljs-string">&quot;../file.ping.dir&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">MERGE2</span> <span class="hljs-attr">max_interval</span>=<span class="hljs-string">&quot;30000&quot;</span>
<span class="hljs-attr">min_interval</span>=<span class="hljs-string">&quot;10000&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">FD_SOCK</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">FD</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">&quot;10000&quot;</span> <span class="hljs-attr">max_tries</span>=<span class="hljs-string">&quot;5&quot;</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">VERIFY_SUSPECT</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">&quot;1500&quot;</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">BARRIER</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">pbcast.NAKACK</span>
<span class="hljs-attr">use_mcast_xmit</span>=<span class="hljs-string">&quot;false&quot;</span>
<span class="hljs-attr">retransmit_timeout</span>=<span class="hljs-string">&quot;300,600,1200,2400,4800&quot;</span>
<span class="hljs-attr">discard_delivered_msgs</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">UNICAST</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">&quot;300,600,1200&quot;</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">pbcast.STABLE</span> <span class="hljs-attr">stability_delay</span>=<span class="hljs-string">&quot;1000&quot;</span> <span class="hljs-attr">desired_avg_gossip</span>=<span class="hljs-string">&quot;50000&quot;</span>
<span class="hljs-attr">max_bytes</span>=<span class="hljs-string">&quot;400000&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">pbcast.GMS</span> <span class="hljs-attr">print_local_addr</span>=<span class="hljs-string">&quot;true&quot;</span> <span class="hljs-attr">join_timeout</span>=<span class="hljs-string">&quot;3000&quot;</span>
<span class="hljs-attr">view_bundling</span>=<span class="hljs-string">&quot;true&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">FC</span> <span class="hljs-attr">max_credits</span>=<span class="hljs-string">&quot;2000000&quot;</span>
<span class="hljs-attr">min_threshold</span>=<span class="hljs-string">&quot;0.10&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">FRAG2</span> <span class="hljs-attr">frag_size</span>=<span class="hljs-string">&quot;60000&quot;</span> /&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">pbcast.STATE_TRANSFER</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">pbcast.FLUSH</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">&quot;0&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">config</span>&gt;</span>
</code></pre>
<p>As it shows, the file content defines a jgroups protocol stacks. If you
want Apache ActiveMQ Artemis to use this stacks for channel creation, you have to make
sure the value of <code>jgroups-file</code> in your broadcast-group/discovery-group
configuration to be the name of this jgroups configuration file. For
example if the above stacks configuration is stored in a file named
&quot;jgroups-stacks.xml&quot; then your <code>jgroups-file</code> should be like</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">jgroups-file</span>&gt;</span>jgroups-stacks.xml<span class="hljs-tag">&lt;/<span class="hljs-name">jgroups-file</span>&gt;</span>
</code></pre>
<h4 id="discovery-groups">Discovery Groups</h4>
<p>While the broadcast group defines how connector information is
broadcasted from a server, a discovery group defines how connector
information is received from a broadcast endpoint (a UDP multicast
address or JGroup channel).</p>
<p>A discovery group maintains a list of connector pairs - one for each
broadcast by a different server. As it receives broadcasts on the
broadcast endpoint from a particular server it updates its entry in the
list for that server.</p>
<p>If it has not received a broadcast from a particular server for a length
of time it will remove that server&apos;s entry from its list.</p>
<p>Discovery groups are used in two places in Apache ActiveMQ Artemis:</p>
<ul>
<li><p>By cluster connections so they know how to obtain an initial
connection to download the topology</p>
</li>
<li><p>By messaging clients so they know how to obtain an initial
connection to download the topology</p>
</li>
</ul>
<p>Although a discovery group will always accept broadcasts, its current
list of available live and backup servers is only ever used when an
initial connection is made, from then server discovery is done over the
normal Apache ActiveMQ Artemis connections.</p>
<blockquote>
<p><strong>Note:</strong></p>
<p>Each discovery group must be configured with broadcast endpoint (UDP
or JGroups) that matches its broadcast group counterpart. For example,
if broadcast is configured using UDP, the discovery group must also
use UDP, and the same multicast address.</p>
</blockquote>
<h4 id="defining-discovery-groups-on-the-server">Defining Discovery Groups on the Server</h4>
<p>For cluster connections, discovery groups are defined in the server side
configuration file <code>broker.xml</code>. All discovery groups
must be defined inside a <code>discovery-groups</code> element. There can be many
discovery groups defined by Apache ActiveMQ Artemis server. Let&apos;s look at an example:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">discovery-groups</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">discovery-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-discovery-group&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">local-bind-address</span>&gt;</span>172.16.9.7<span class="hljs-tag">&lt;/<span class="hljs-name">local-bind-address</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">group-address</span>&gt;</span>231.7.7.7<span class="hljs-tag">&lt;/<span class="hljs-name">group-address</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">group-port</span>&gt;</span>9876<span class="hljs-tag">&lt;/<span class="hljs-name">group-port</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">refresh-timeout</span>&gt;</span>10000<span class="hljs-tag">&lt;/<span class="hljs-name">refresh-timeout</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">discovery-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">discovery-groups</span>&gt;</span>
</code></pre>
<p>We&apos;ll consider each parameter of the discovery group:</p>
<ul>
<li><p><code>name</code> attribute. Each discovery group must have a unique name per
server.</p>
</li>
<li><p><code>local-bind-address</code>. If you are running with multiple network
interfaces on the same machine, you may want to specify that the
discovery group listens only only a specific interface. To do this
you can specify the interface address with this parameter. This
parameter is optional. This is a UDP specific attribute.</p>
</li>
<li><p><code>group-address</code>. This is the multicast IP address of the group to
listen on. It should match the <code>group-address</code> in the broadcast
group that you wish to listen from. This parameter is mandatory.
This is a UDP specific attribute.</p>
</li>
<li><p><code>group-port</code>. This is the UDP port of the multicast group. It should
match the <code>group-port</code> in the broadcast group that you wish to
listen from. This parameter is mandatory. This is a UDP specific
attribute.</p>
</li>
<li><p><code>refresh-timeout</code>. This is the period the discovery group waits
after receiving the last broadcast from a particular server before
removing that servers connector pair entry from its list. You would
normally set this to a value significantly higher than the
<code>broadcast-period</code> on the broadcast group otherwise servers might
intermittently disappear from the list even though they are still
broadcasting due to slight differences in timing. This parameter is
optional, the default value is <code>10000</code> milliseconds (10 seconds).</p>
</li>
</ul>
<p>Here is another example that defines a JGroups discovery group:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">discovery-groups</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">discovery-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-broadcast-group&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">jgroups-file</span>&gt;</span>test-jgroups-file_ping.xml<span class="hljs-tag">&lt;/<span class="hljs-name">jgroups-file</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">jgroups-channel</span>&gt;</span>activemq_broadcast_channel<span class="hljs-tag">&lt;/<span class="hljs-name">jgroups-channel</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">refresh-timeout</span>&gt;</span>10000<span class="hljs-tag">&lt;/<span class="hljs-name">refresh-timeout</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">discovery-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">discovery-groups</span>&gt;</span>
</code></pre>
<p>To receive broadcast from JGroups channels, one must specify two
attributes, <code>jgroups-file</code> and <code>jgroups-channel</code>, as discussed in
details as following:</p>
<ul>
<li><p><code>jgroups-file</code> attribute. This is the name of JGroups configuration
file. It will be used to initialize JGroups channels. Make sure the
file is in the java resource path so that Apache ActiveMQ Artemis can load it.</p>
</li>
<li><p><code>jgroups-channel</code> attribute. The name that JGroups channels connect
to for receiving broadcasts.</p>
</li>
</ul>
<blockquote>
<p><strong>Note:</strong></p>
<p>The JGroups attributes (<code>jgroups-file</code> and <code>jgroups-channel</code>) and UDP
specific attributes described above are exclusive of each other. Only
one set can be specified in a discovery group configuration. Don&apos;t mix
them!</p>
</blockquote>
<h4 id="discovery-groups-on-the-client-side">Discovery Groups on the Client Side</h4>
<p>Let&apos;s discuss how to configure an Apache ActiveMQ Artemis client to use discovery to
discover a list of servers to which it can connect. The way to do this
differs depending on whether you&apos;re using JMS or the core API.</p>
<h5 id="configuring-client-discovery">Configuring client discovery</h5>
<p>Use the <code>udp</code> URL scheme and a host:port combination matches the group-address and
group-port from the corresponding <code>broadcast-group</code> on the server:</p>
<pre><code>udp://231.7.7.7:9876
</code></pre><p>The element <code>discovery-group-ref</code> specifies the name of a discovery
group defined in <code>broker.xml</code>.</p>
<p>Connections created using this URI will be load-balanced across the
list of servers that the discovery group maintains by listening on
the multicast address specified in the discovery group configuration.</p>
<p>The aforementioned <code>refreshTimeout</code> parameter can be set directly in the URI.</p>
<p>There is also a URL parameter named <code>initialWaitTimeout</code>. If the corresponding
JMS connection factory or core session factory is used immediately after
creation then it may not have had enough time to received broadcasts from
all the nodes in the cluster. On first usage, the connection factory will
make sure it waits this long since creation before creating the first
connection. The default value for this parameter is <code>10000</code> milliseconds.</p>
<h3 id="discovery-using-static-connectors">Discovery using static Connectors</h3>
<p>Sometimes it may be impossible to use UDP on the network you are using.
In this case its possible to configure a connection with an initial list
of possible servers. This could be just one server that you know will
always be available or a list of servers where at least one will be
available.</p>
<p>This doesn&apos;t mean that you have to know where all your servers are going
to be hosted, you can configure these servers to use the reliable
servers to connect to. Once they are connected their connection details
will be propagated via the server it connects to</p>
<h4 id="configuring-a-cluster-connection">Configuring a Cluster Connection</h4>
<p>For cluster connections there is no extra configuration needed, you just
need to make sure that any connectors are defined in the usual manner,
(see <a href="configuring-transports.html">Configuring the Transport</a> for more information on connectors). These are then referenced by
the cluster connection configuration.</p>
<h4 id="configuring-a-client-connection">Configuring a Client Connection</h4>
<p>A static list of possible servers can also be used by a normal client.</p>
<h5 id="configuring-client-discovery">Configuring client discovery</h5>
<p>A list of servers to be used for the initial connection attempt can be
specified in the connection URI using a syntax with <code>()</code>, e.g.:</p>
<pre><code>(tcp://myhost:61616,tcp://myhost2:61616)?reconnectAttempts=5
</code></pre><p>The brackets are expanded so the same query can be appended after the last
bracket for ease.</p>
<h2 id="server-side-message-load-balancing">Server-Side Message Load Balancing</h2>
<p>If cluster connections are defined between nodes of a cluster, then
Apache ActiveMQ Artemis will load balance messages arriving at a particular node from a
client.</p>
<p>Let&apos;s take a simple example of a cluster of four nodes A, B, C, and D
arranged in a <em>symmetric cluster</em> (described in Symmetrical Clusters section). We have a queue
called <code>OrderQueue</code> deployed on each node of the cluster.</p>
<p>We have client Ca connected to node A, sending orders to the server. We
have also have order processor clients Pa, Pb, Pc, and Pd connected to
each of the nodes A, B, C, D. If no cluster connection was defined on
node A, then as order messages arrive on node A they will all end up in
the <code>OrderQueue</code> on node A, so will only get consumed by the order
processor client attached to node A, Pa.</p>
<p>If we define a cluster connection on node A, then as ordered messages
arrive on node A instead of all of them going into the local
<code>OrderQueue</code> instance, they are distributed in a round-robin fashion
between all the nodes of the cluster. The messages are forwarded from
the receiving node to other nodes of the cluster. This is all done on
the server side, the client maintains a single connection to node A.</p>
<p>For example, messages arriving on node A might be distributed in the
following order between the nodes: B, D, C, A, B, D, C, A, B, D. The
exact order depends on the order the nodes started up, but the algorithm
used is round robin.</p>
<p>Apache ActiveMQ Artemis cluster connections can be configured to always blindly load
balance messages in a round robin fashion irrespective of whether there
are any matching consumers on other nodes, but they can be a bit
cleverer than that and also be configured to only distribute to other
nodes if they have matching consumers. We&apos;ll look at both these cases in
turn with some examples, but first we&apos;ll discuss configuring cluster
connections in general.</p>
<h3 id="configuring-cluster-connections">Configuring Cluster Connections</h3>
<p>Cluster connections group servers into clusters so that messages can be
load balanced between the nodes of the cluster. Let&apos;s take a look at a
typical cluster connection. Cluster connections are always defined in
<code>broker.xml</code> inside a <code>cluster-connection</code> element.
There can be zero or more cluster connections defined per Apache ActiveMQ Artemis
server.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">cluster-connections</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-cluster&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">address</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">address</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>netty-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">check-period</span>&gt;</span>1000<span class="hljs-tag">&lt;/<span class="hljs-name">check-period</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connection-ttl</span>&gt;</span>5000<span class="hljs-tag">&lt;/<span class="hljs-name">connection-ttl</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">min-large-message-size</span>&gt;</span>50000<span class="hljs-tag">&lt;/<span class="hljs-name">min-large-message-size</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">call-timeout</span>&gt;</span>5000<span class="hljs-tag">&lt;/<span class="hljs-name">call-timeout</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">retry-interval</span>&gt;</span>500<span class="hljs-tag">&lt;/<span class="hljs-name">retry-interval</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">retry-interval-multiplier</span>&gt;</span>1.0<span class="hljs-tag">&lt;/<span class="hljs-name">retry-interval-multiplier</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">max-retry-interval</span>&gt;</span>5000<span class="hljs-tag">&lt;/<span class="hljs-name">max-retry-interval</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">initial-connect-attempts</span>&gt;</span>-1<span class="hljs-tag">&lt;/<span class="hljs-name">initial-connect-attempts</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">reconnect-attempts</span>&gt;</span>-1<span class="hljs-tag">&lt;/<span class="hljs-name">reconnect-attempts</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">use-duplicate-detection</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">use-duplicate-detection</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">message-load-balancing</span>&gt;</span>ON_DEMAND<span class="hljs-tag">&lt;/<span class="hljs-name">message-load-balancing</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">max-hops</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">max-hops</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">confirmation-window-size</span>&gt;</span>32000<span class="hljs-tag">&lt;/<span class="hljs-name">confirmation-window-size</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">call-failover-timeout</span>&gt;</span>30000<span class="hljs-tag">&lt;/<span class="hljs-name">call-failover-timeout</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">notification-interval</span>&gt;</span>1000<span class="hljs-tag">&lt;/<span class="hljs-name">notification-interval</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">notification-attempts</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">notification-attempts</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">discovery-group-ref</span> <span class="hljs-attr">discovery-group-name</span>=<span class="hljs-string">&quot;my-discovery-group&quot;</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-connection</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-connections</span>&gt;</span>
</code></pre>
<p>In the above cluster connection all parameters have been explicitly
specified. The following shows all the available configuration options</p>
<ul>
<li><p><code>address</code> Each cluster connection only applies to addresses that
match the specified <code>address</code> field. An address is matched on the
cluster connection when it begins with the string specified in this
field. The <code>address</code> field on a cluster connection also supports comma
separated lists and an exclude syntax <code>!</code>. To prevent an address
from being matched on this cluster connection, prepend a cluster
connection address string with <code>!</code>.</p>
<p>In the case shown above the cluster connection will load balance
messages sent to all addresses (since it&apos;s empty).</p>
<p>The address can be any value and you can have many cluster
connections with different values of <code>address</code>, simultaneously
balancing messages for those addresses, potentially to different
clusters of servers. By having multiple cluster connections on
different addresses a single Apache ActiveMQ Artemis Server can effectively take
part in multiple clusters simultaneously.</p>
<p>Be careful not to have multiple cluster connections with overlapping
values of <code>address</code>, e.g. &quot;europe&quot; and &quot;europe.news&quot; since this
could result in the same messages being distributed between more
than one cluster connection, possibly resulting in duplicate
deliveries.</p>
<p>Examples:</p>
<ul>
<li>&apos;eu&apos;
matches all addresses starting with &apos;eu&apos;</li>
<li>&apos;!eu&apos;
matches all address except for those starting with &apos;eu&apos;</li>
<li>&apos;eu.uk,eu.de&apos;
matches all addresses starting with either &apos;eu.uk&apos; or
&apos;eu.de&apos;</li>
<li>&apos;eu,!eu.uk&apos;
matches all addresses starting with &apos;eu&apos; but not those
starting with &apos;eu.uk&apos;</li>
</ul>
<p><strong>Note:</strong>:</p>
<ul>
<li>Address exclusion will always takes precedence over address
inclusion.</li>
<li>Address matching on cluster connections does not support
wild-card matching.</li>
</ul>
</li>
<li><p><code>connector-ref</code>. This is the connector which will be sent to other
nodes in the cluster so they have the correct cluster topology.</p>
<p>This parameter is mandatory.</p>
</li>
<li><p><code>check-period</code>. The period (in milliseconds) used to check if the
cluster connection has failed to receive pings from another server.
Default is 30000.</p>
</li>
<li><p><code>connection-ttl</code>. This is how long a cluster connection should stay
alive if it stops receiving messages from a specific node in the
cluster. Default is 60000.</p>
</li>
<li><p><code>min-large-message-size</code>. If the message size (in bytes) is larger
than this value then it will be split into multiple segments when
sent over the network to other cluster members. Default is 102400.</p>
</li>
<li><p><code>call-timeout</code>. When a packet is sent via a cluster connection and
is a blocking call, i.e. for acknowledgements, this is how long it
will wait (in milliseconds) for the reply before throwing an
exception. Default is 30000.</p>
</li>
<li><p><code>retry-interval</code>. We mentioned before that, internally, cluster
connections cause bridges to be created between the nodes of the
cluster. If the cluster connection is created and the target node
has not been started, or say, is being rebooted, then the cluster
connections from other nodes will retry connecting to the target
until it comes back up, in the same way as a bridge does.</p>
<p>This parameter determines the interval in milliseconds between retry
attempts. It has the same meaning as the <code>retry-interval</code> on a
bridge (as described in <a href="core-bridges.html">Core Bridges</a>).</p>
<p>This parameter is optional and its default value is <code>500</code>
milliseconds.</p>
</li>
<li><p><code>retry-interval-multiplier</code>. This is a multiplier used to increase
the <code>retry-interval</code> after each reconnect attempt, default is 1.</p>
</li>
<li><p><code>max-retry-interval</code>. The maximum delay (in milliseconds) for
retries. Default is 2000.</p>
</li>
<li><p><code>initial-connect-attempts</code>. The number of times the system will try
to connect a node in the cluster initially. If the max-retry is
achieved this node will be considered permanently down and the
system will not route messages to this node. Default is -1 (infinite
retries).</p>
</li>
<li><p><code>reconnect-attempts</code>. The number of times the system will try to
reconnect to a node in the cluster. If the max-retry is achieved
this node will be considered permanently down and the system will
stop routing messages to this node. Default is -1 (infinite
retries).</p>
</li>
<li><p><code>use-duplicate-detection</code>. Internally cluster connections use
bridges to link the nodes, and bridges can be configured to add a
duplicate id property in each message that is forwarded. If the
target node of the bridge crashes and then recovers, messages might
be resent from the source node. By enabling duplicate detection any
duplicate messages will be filtered out and ignored on receipt at
the target node.</p>
<p>This parameter has the same meaning as <code>use-duplicate-detection</code> on
a bridge. For more information on duplicate detection, please see <a href="duplicate-detection.html">Duplicate Detection</a>.
Default is true.</p>
</li>
<li><p><code>message-load-balancing</code>. This parameter determines if/how
messages will be distributed between other nodes of the cluster.
It can be one of three values - <code>OFF</code>, <code>STRICT</code>, or <code>ON_DEMAND</code>
(default). This parameter replaces the deprecated
<code>forward-when-no-consumers</code> parameter.</p>
<p>If this is set to <code>OFF</code> then messages will never be forwarded to
another node in the cluster</p>
<p>If this is set to <code>STRICT</code> then each incoming message will be round
robin&apos;d even though the same queues on the other nodes of the
cluster may have no consumers at all, or they may have consumers
that have non matching message filters (selectors). Note that
Apache ActiveMQ Artemis will <em>not</em> forward messages to other nodes
if there are no <em>queues</em> of the same name on the other nodes, even
if this parameter is set to <code>STRICT</code>. Using <code>STRICT</code> is like setting
the legacy <code>forward-when-no-consumers</code> parameter to <code>true</code>.</p>
<p>If this is set to <code>ON_DEMAND</code> then Apache ActiveMQ Artemis will only
forward messages to other nodes of the cluster if the address to which
they are being forwarded has queues which have consumers, and if those
consumers have message filters (selectors) at least one of those
selectors must match the message. Using <code>ON_DEMAND</code> is like setting
the legacy <code>forward-when-no-consumers</code> parameter to <code>false</code>.</p>
<p>Keep in mind that this message forwarding/balancing is what we call
&quot;initial distribution.&quot; It is different than <em>redistribution</em> which
is <a href="#message-redistribution">discussed below</a>. This distinction is
important because redistribution is configured differently and has
unique semantics (e.g. it <em>does not</em> support filters (selectors)).</p>
<p>Default is <code>ON_DEMAND</code>.</p>
</li>
<li><p><code>max-hops</code>. When a cluster connection decides the set of nodes to
which it might load balance a message, those nodes do not have to be
directly connected to it via a cluster connection. Apache ActiveMQ Artemis can be
configured to also load balance messages to nodes which might be
connected to it only indirectly with other Apache ActiveMQ Artemis servers as
intermediates in a chain.</p>
<p>This allows Apache ActiveMQ Artemis to be configured in more complex topologies and
still provide message load balancing. We&apos;ll discuss this more later
in this chapter.</p>
<p>The default value for this parameter is <code>1</code>, which means messages
are only load balanced to other Apache ActiveMQ Artemis serves which are directly
connected to this server. This parameter is optional.</p>
</li>
<li><p><code>confirmation-window-size</code>. The size (in bytes) of the window used
for sending confirmations from the server connected to. So once the
server has received <code>confirmation-window-size</code> bytes it notifies its
client, default is 1048576. A value of -1 means no window.</p>
</li>
<li><p><code>producer-window-size</code>. The size for producer flow control over cluster connection.
it&apos;s by default disabled through the cluster connection bridge but you may want
to set a value if you are using really large messages in cluster. A value of -1 means no window.</p>
</li>
<li><p><code>call-failover-timeout</code>. Similar to <code>call-timeout</code> but used when a
call is made during a failover attempt. Default is -1 (no timeout).</p>
</li>
<li><p><code>notification-interval</code>. How often (in milliseconds) the cluster
connection should broadcast itself when attaching to the cluster.
Default is 1000.</p>
</li>
<li><p><code>notification-attempts</code>. How many times the cluster connection
should broadcast itself when connecting to the cluster. Default is
2.</p>
</li>
<li><p><code>discovery-group-ref</code>. This parameter determines which discovery
group is used to obtain the list of other servers in the cluster
that this cluster connection will make connections to.</p>
</li>
</ul>
<p>Alternatively if you would like your cluster connections to use a static
list of servers for discovery then you can do it like this.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-cluster&quot;</span>&gt;</span>
...
<span class="hljs-tag">&lt;<span class="hljs-name">static-connectors</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>server0-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>server1-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">static-connectors</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-connection</span>&gt;</span>
</code></pre>
<p>Here we have defined 2 servers that we know for sure will that at least
one will be available. There may be many more servers in the cluster but
these will; be discovered via one of these connectors once an initial
connection has been made.</p>
<h3 id="cluster-user-credentials">Cluster User Credentials</h3>
<p>When creating connections between nodes of a cluster to form a cluster
connection, Apache ActiveMQ Artemis uses a cluster user and cluster password which is
defined in <code>broker.xml</code>:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">cluster-user</span>&gt;</span>ACTIVEMQ.CLUSTER.ADMIN.USER<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-user</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">cluster-password</span>&gt;</span>CHANGE ME!!<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-password</span>&gt;</span>
</code></pre>
<blockquote>
<p><strong>Warning</strong></p>
<p>It is imperative that these values are changed from their default, or
remote clients will be able to make connections to the server using
the default values. If they are not changed from the default, Apache ActiveMQ Artemis
will detect this and pester you with a warning on every start-up.</p>
</blockquote>
<h2 id="client-side-load-balancing">Client-Side Load balancing</h2>
<p>With Apache ActiveMQ Artemis client-side load balancing, subsequent sessions created
using a single session factory can be connected to different nodes of
the cluster. This allows sessions to spread smoothly across the nodes of
a cluster and not be &quot;clumped&quot; on any particular node.</p>
<p>The load balancing policy to be used by the client factory is
configurable. Apache ActiveMQ Artemis provides four out-of-the-box load balancing
policies, and you can also implement your own and use that.</p>
<p>The out-of-the-box policies are</p>
<ul>
<li><p>Round Robin. With this policy the first node is chosen randomly then
each subsequent node is chosen sequentially in the same order.</p>
<p>For example nodes might be chosen in the order B, C, D, A, B, C, D,
A, B or D, A, B, C, D, A, B, C, D or C, D, A, B, C, D, A, B, C.</p>
<p>Use
<code>org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy</code>
as the <code>&lt;connection-load-balancing-policy-class-name&gt;</code>.</p>
</li>
<li><p>Random. With this policy each node is chosen randomly.</p>
<p>Use
<code>org.apache.activemq.artemis.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy</code>
as the <code>&lt;connection-load-balancing-policy-class-name&gt;</code>.</p>
</li>
<li><p>Random Sticky. With this policy the first node is chosen randomly
and then re-used for subsequent connections.</p>
<p>Use
<code>org.apache.activemq.artemis.api.core.client.loadbalance.RandomStickyConnectionLoadBalancingPolicy</code>
as the <code>&lt;connection-load-balancing-policy-class-name&gt;</code>.</p>
</li>
<li><p>First Element. With this policy the &quot;first&quot; (i.e. 0th) node is
always returned.</p>
<p>Use
<code>org.apache.activemq.artemis.api.core.client.loadbalance.FirstElementConnectionLoadBalancingPolicy</code>
as the <code>&lt;connection-load-balancing-policy-class-name&gt;</code>.</p>
</li>
</ul>
<p>You can also implement your own policy by implementing the interface
<code>org.apache.activemq.artemis.api.core.client.loadbalance.ConnectionLoadBalancingPolicy</code></p>
<p>Specifying which load balancing policy to use differs whether you are
using JMS or the core API. If you don&apos;t specify a policy then the
default will be used which is
<code>org.apache.activemq.artemis.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy</code>.</p>
<p>The parameter <code>connectionLoadBalancingPolicyClassName</code> can be set on the URI to
configure what load balancing policy to use:</p>
<pre><code>tcp://localhost:61616?connectionLoadBalancingPolicyClassName=org.apache.activemq.artemis.api.core.client.loadbalance.RandomConnectionLoadBalancingPolicy
</code></pre><p>The set of servers over which the factory load balances can be
determined in one of two ways:</p>
<ul>
<li><p>Specifying servers explicitly in the URL. This also requires setting
the <code>useTopologyForLoadBalancing</code> parameter to <code>false</code> on the URL.</p>
</li>
<li><p>Using discovery. This is the default behavior.</p>
</li>
</ul>
<h2 id="specifying-members-of-a-cluster-explicitly">Specifying Members of a Cluster Explicitly</h2>
<p>Sometimes you want to explicitly define a cluster more explicitly, that
is control which server connect to each other in the cluster. This is
typically used to form non symmetrical clusters such as chain cluster or
ring clusters. This can only be done using a static list of connectors
and is configured as follows:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;my-cluster&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">address</span>/&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>netty-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">retry-interval</span>&gt;</span>500<span class="hljs-tag">&lt;/<span class="hljs-name">retry-interval</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">use-duplicate-detection</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">use-duplicate-detection</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">message-load-balancing</span>&gt;</span>STRICT<span class="hljs-tag">&lt;/<span class="hljs-name">message-load-balancing</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">max-hops</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">max-hops</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">static-connectors</span> <span class="hljs-attr">allow-direct-connections-only</span>=<span class="hljs-string">&quot;true&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">connector-ref</span>&gt;</span>server1-connector<span class="hljs-tag">&lt;/<span class="hljs-name">connector-ref</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">static-connectors</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">cluster-connection</span>&gt;</span>
</code></pre>
<p>In this example we have set the attribute
<code>allow-direct-connections-only</code> which means that the only server that
this server can create a cluster connection to is server1-connector.
This means you can explicitly create any cluster topology you want.</p>
<h2 id="message-redistribution">Message Redistribution</h2>
<p>Another important part of clustering is message redistribution. Earlier
we learned how server side message load balancing round robins messages
across the cluster. If <code>message-load-balancing</code> is <code>OFF</code> or <code>ON_DEMAND</code>
then messages won&apos;t be forwarded to nodes which don&apos;t have matching
consumers. This is great and ensures that messages aren&apos;t moved to a
queue which has no consumers to consume them. However, there is a
situation it doesn&apos;t solve: What happens if the consumers on a queue
close after the messages have been sent to the node? If there are no
consumers on the queue the message won&apos;t get consumed and we have a
<em>starvation</em> situation.</p>
<p>This is where message redistribution comes in. With message
redistribution Apache ActiveMQ Artemis can be configured to automatically
<em>redistribute</em> messages from queues which have no consumers back to
other nodes in the cluster which do have matching consumers. To enable
this functionality <code>message-load-balancing</code> must be <code>ON_DEMAND</code>.</p>
<p>Message redistribution can be configured to kick in immediately after
the last consumer on a queue is closed, or to wait a configurable delay
after the last consumer on a queue is closed before redistributing. By
default message redistribution is disabled.</p>
<p>Message redistribution can be configured on a per address basis, by
specifying the redistribution delay in the address settings. For more
information on configuring address settings, please see <a href="address-model.html#configuring-addresses-and-queues-via-address-settings">Configuring Addresses and Queues via Address Settings</a>.</p>
<p>Here&apos;s an address settings snippet from <code>broker.xml</code>
showing how message redistribution is enabled for a set of queues:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">address-settings</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">address-setting</span> <span class="hljs-attr">match</span>=<span class="hljs-string">&quot;#&quot;</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">redistribution-delay</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">redistribution-delay</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">address-setting</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">address-settings</span>&gt;</span>
</code></pre>
<p>The above <code>address-settings</code> block would set a <code>redistribution-delay</code> of
<code>0</code> for any queue which is bound to any address. So the above would enable
instant (no delay) redistribution for all addresses.</p>
<p>The attribute <code>match</code> can be an exact match or it can be a string that
conforms to the Apache ActiveMQ Artemis wildcard syntax (described in <a href="wildcard-syntax.html">Wildcard Syntax</a>).</p>
<p>The element <code>redistribution-delay</code> defines the delay in milliseconds
after the last consumer is closed on a queue before redistributing
messages from that queue to other nodes of the cluster which do have
matching consumers. A delay of zero means the messages will be
immediately redistributed. A value of <code>-1</code> signifies that messages will
never be redistributed. The default value is <code>-1</code>.</p>
<p>It often makes sense to introduce a delay before redistributing as it&apos;s
a common case that a consumer closes but another one quickly is created
on the same queue, in such a case you probably don&apos;t want to
redistribute immediately since the new consumer will arrive shortly.</p>
<h4 id="redistribution-and-filters-selectors">Redistribution and filters (selectors)</h4>
<p>Although &quot;initial distribution&quot; (described above) does support filters
(selectors), redistribution does <em>not</em> support filters. Consider this
scenario:</p>
<ol>
<li>A cluster of 2 nodes - <code>A</code> and <code>B</code> - using a <code>redistribution-delay</code> of
<code>0</code> and a <code>message-load-balancing</code> of <code>ON_DEMAND</code>.</li>
<li><code>A</code> and <code>B</code> each has the queue <code>foo</code>.</li>
<li>A producer sends a message which is routed to queue <code>foo</code> on node <code>A</code>.
The message has property named <code>myProperty</code> with a value of <code>10</code>.</li>
<li>A consumer connects to queue <code>foo</code> on node <code>A</code> with the filter
<code>myProperty=5</code>. This filter doesn&apos;t match the message.</li>
<li>A consumer connects to queue <code>foo</code> on node <code>B</code> with the filter
<code>myProperty=10</code>. This filter <em>does</em> match the message .</li>
</ol>
<p>Despite the fact that the filter of the consumer on queue <code>foo</code> on node <code>B</code>
matches the message, the message will <em>not</em> be redistributed from node <code>A</code> to
node <code>B</code> because a consumer for the queue exists on node <code>A</code>.</p>
<p>Not supporting redistribution based on filters was an explicit design decision
in order to avoid two main problems - queue scanning and unnecessary
redistribution.</p>
<p>From a performance perspective a consumer with a filter on a queue is already
costly due to the scanning that the broker must do on the queue to find
matching messages. In general, this is a bit of an anti-pattern as it turns
the broker into something akin to a database where you can &quot;select&quot; the data
you want using a filter. If brokers are configured in a cluster and a consumer
with a filter connects and no matches are found after scanning the local queue
then potentially every instance of that queue in the cluster would need to be
scanned. This turns into a bit of a scalability nightmare with lots of consumers
(especially short-lived consumers) with filters connecting &amp; disconnecting
frequently. The time &amp; computing resources used for queue scanning would go
through the roof.</p>
<p>It is also possible to get into a pathological situation where short-lived
consumers with filters connect to nodes around the cluster and messages get
redistributed back and forth between nodes without ever actually being consumed.</p>
<p>One common use-case for consumers with filters (selectors) on queues is
request/reply using a correlation ID. Following the standard pattern can be
problematic in a cluster due to the lack of redistribution based on filters
already described. However, there is a simple way to ensure an application
using this request/reply pattern gets its reply even when using a correlation
ID filter in a cluster - create the consumer before the request is sent. This
will ensure that when the reply is sent it will be routed the proper cluster
node since &quot;<em>initial</em> distribution&quot; (described above) does support filters.
For example, in the scenario outlined above if steps 3 and 5 were switched
(i.e. if the consumers were created before the message was sent) then the
consumer on node <code>B</code> would in fact receive the message.</p>
<h2 id="cluster-topologies">Cluster topologies</h2>
<p>Apache ActiveMQ Artemis clusters can be connected together in many different
topologies, let&apos;s consider the two most common ones here</p>
<h3 id="symmetric-cluster">Symmetric cluster</h3>
<p>A symmetric cluster is probably the most common cluster topology.</p>
<p>With a symmetric cluster every node in the cluster is connected to every
other node in the cluster. In other words every node in the cluster is
no more than one hop away from every other node.</p>
<p>To form a symmetric cluster every node in the cluster defines a cluster
connection with the attribute <code>max-hops</code> set to <code>1</code>. Typically the
cluster connection will use server discovery in order to know what other
servers in the cluster it should connect to, although it is possible to
explicitly define each target server too in the cluster connection if,
for example, UDP is not available on your network.</p>
<p>With a symmetric cluster each node knows about all the queues that exist
on all the other nodes and what consumers they have. With this knowledge
it can determine how to load balance and redistribute messages around
the nodes.</p>
<p>Don&apos;t forget <a href="#copy-warning">this warning</a> when creating a symmetric
cluster.</p>
<h3 id="chain-cluster">Chain cluster</h3>
<p>With a chain cluster, each node in the cluster is not connected to every
node in the cluster directly, instead the nodes form a chain with a node
on each end of the chain and all other nodes just connecting to the
previous and next nodes in the chain.</p>
<p>An example of this would be a three node chain consisting of nodes A, B
and C. Node A is hosted in one network and has many producer clients
connected to it sending order messages. Due to corporate policy, the
order consumer clients need to be hosted in a different network, and
that network is only accessible via a third network. In this setup node
B acts as a mediator with no producers or consumers on it. Any messages
arriving on node A will be forwarded to node B, which will in turn
forward them to node C where they can get consumed. Node A does not need
to directly connect to C, but all the nodes can still act as a part of
the cluster.</p>
<p>To set up a cluster in this way, node A would define a cluster
connection that connects to node B, and node B would define a cluster
connection that connects to node C. In this case we only want cluster
connections in one direction since we&apos;re only moving messages from node
A-&gt;B-&gt;C and never from C-&gt;B-&gt;A.</p>
<p>For this topology we would set <code>max-hops</code> to <code>2</code>. With a value of <code>2</code>
the knowledge of what queues and consumers that exist on node C would be
propagated from node C to node B to node A. Node A would then know to
distribute messages to node B when they arrive, even though node B has
no consumers itself, it would know that a further hop away is node C
which does have consumers.</p>
<h3 id="scaling-down">Scaling Down</h3>
<p>Apache ActiveMQ Artemis supports scaling down a cluster with no message loss (even for
non-durable messages). This is especially useful in certain environments
(e.g. the cloud) where the size of a cluster may change relatively
frequently. When scaling up a cluster (i.e. adding nodes) there is no
risk of message loss, but when scaling down a cluster (i.e. removing
nodes) the messages on those nodes would be lost unless the broker sent
them to another node in the cluster. Apache ActiveMQ Artemis can be configured to do
just that.</p>
<p>The simplest way to enable this behavior is to set <code>scale-down</code> to
<code>true</code>. If the server is clustered and <code>scale-down</code> is <code>true</code> then when
the server is shutdown gracefully (i.e. stopped without crashing) it
will find another node in the cluster and send <em>all</em> of its messages
(both durable and non-durable) to that node. The messages are processed
in order and go to the <em>back</em> of the respective queues on the other node
(just as if the messages were sent from an external client for the first
time).</p>
<p>If more control over where the messages go is required then specify
<code>scale-down-group-name</code>. Messages will only be sent to another node in
the cluster that uses the same <code>scale-down-group-name</code> as the server
being shutdown.</p>
<blockquote>
<p><strong>Warning</strong></p>
<p>If cluster nodes are grouped together with different
<code>scale-down-group-name</code> values beware. If all the nodes in a single
group are shut down then the messages from that node/group will be
lost.</p>
</blockquote>
<p>If the server is using multiple <code>cluster-connection</code> then use
<code>scale-down-clustername</code> to identify the name of the
<code>cluster-connection</code> which should be used for scaling down.</p>
</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
</div>
</div>
</div>
<a href="duplicate-detection.html" class="navigation navigation-prev " aria-label="Previous page: Duplicate Message Detection">
<i class="fa fa-angle-left"></i>
</a>
<a href="federation.html" class="navigation navigation-next " aria-label="Next page: Federation">
<i class="fa fa-angle-right"></i>
</a>
</div>
<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"Clusters","level":"1.59","depth":1,"next":{"title":"Federation","level":"1.60","depth":1,"path":"federation.md","ref":"federation.md","articles":[{"title":"Address Federation","level":"1.60.1","depth":2,"path":"federation-address.md","ref":"federation-address.md","articles":[]},{"title":"Queue Federation","level":"1.60.2","depth":2,"path":"federation-queue.md","ref":"federation-queue.md","articles":[]}]},"previous":{"title":"Duplicate Message Detection","level":"1.58","depth":1,"path":"duplicate-detection.md","ref":"duplicate-detection.md","articles":[]},"dir":"ltr"},"config":{"plugins":[],"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"highlight":{},"search":{},"lunr":{"maxIndexSize":1000000},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"github":"apache/activemq-artemis","theme":"default","githubHost":"https://github.com/","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"title":"ActiveMQ Artemis Documentation","links":{"home":"http://activemq.apache.org/artemis","issues":"https://issues.apache.org/jira/browse/ARTEMIS","contribute":"http://activemq.apache.org/contributing.html"},"gitbook":"3.x.x","description":"ActiveMQ Artemis User Guide and Reference Documentation"},"file":{"path":"clusters.md","mtime":"2020-04-27T19:30:24.000Z","type":"markdown"},"gitbook":{"version":"3.1.1","time":"2020-04-29T20:47:49.444Z"},"basePath":".","book":{"language":""}});
});
</script>
</div>
<script src="gitbook/gitbook.js"></script>
<script src="gitbook/theme.js"></script>
<script src="gitbook/gitbook-plugin-search/search-engine.js"></script>
<script src="gitbook/gitbook-plugin-search/search.js"></script>
<script src="gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
<script src="gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
<script src="gitbook/gitbook-plugin-sharing/buttons.js"></script>
<script src="gitbook/gitbook-plugin-fontsettings/fontsettings.js"></script>
</body>
</html>