| |
| <!DOCTYPE HTML> |
| <html lang="" > |
| <head> |
| <meta charset="UTF-8"> |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <title>Clusters ยท ActiveMQ Artemis Documentation</title> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
| <meta name="description" content=""> |
| <meta name="generator" content="GitBook 3.2.3"> |
| |
| |
| |
| |
| <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" > |
| |
| <span> |
| |
| |
| Address |
| |
| </span> |
| |
| |
| |
| <ul class="articles"> |
| |
| |
| <li class="chapter " data-level="1.10.1" data-path="address-model.html"> |
| |
| <a href="address-model.html"> |
| |
| |
| Model |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.10.2" data-path="address-settings.html"> |
| |
| <a href="address-settings.html"> |
| |
| |
| Settings |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| </ul> |
| |
| </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> |
| |
| |
| |
| <ul class="articles"> |
| |
| |
| <li class="chapter " data-level="1.12.1" data-path="amqp-broker-connections.html"> |
| |
| <a href="amqp-broker-connections.html"> |
| |
| |
| Broker Connections |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| </ul> |
| |
| </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> |
| |
| |
| |
| <ul class="articles"> |
| |
| |
| <li class="chapter " data-level="1.19.1" data-path="client-classpath-jms.html"> |
| |
| <a href="client-classpath-jms.html"> |
| |
| |
| JMS |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.19.2" data-path="client-classpath-jakarta.html"> |
| |
| <a href="client-classpath-jakarta.html"> |
| |
| |
| Jakarta |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| </ul> |
| |
| </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="non-destructive-queues.html"> |
| |
| <a href="non-destructive-queues.html"> |
| |
| |
| Non-Destructive Queues |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.41" data-path="ring-queues.html"> |
| |
| <a href="ring-queues.html"> |
| |
| |
| Ring Queues |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.42" data-path="retroactive-addresses.html"> |
| |
| <a href="retroactive-addresses.html"> |
| |
| |
| Retroactive Addresses |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.43" data-path="exclusive-queues.html"> |
| |
| <a href="exclusive-queues.html"> |
| |
| |
| Exclusive Queues |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.44" data-path="message-grouping.html"> |
| |
| <a href="message-grouping.html"> |
| |
| |
| Message Grouping |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.45" data-path="consumer-priority.html"> |
| |
| <a href="consumer-priority.html"> |
| |
| |
| Consumer Priority |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.46" data-path="pre-acknowledge.html"> |
| |
| <a href="pre-acknowledge.html"> |
| |
| |
| Extra Acknowledge Modes |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.47" data-path="management.html"> |
| |
| <a href="management.html"> |
| |
| |
| Management |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.48" data-path="management-console.html"> |
| |
| <a href="management-console.html"> |
| |
| |
| Management Console |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.49" data-path="metrics.html"> |
| |
| <a href="metrics.html"> |
| |
| |
| Metrics |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.50" data-path="security.html"> |
| |
| <a href="security.html"> |
| |
| |
| Security |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.51" data-path="masking-passwords.html"> |
| |
| <a href="masking-passwords.html"> |
| |
| |
| Masking Passwords |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.52" data-path="broker-plugins.html"> |
| |
| <a href="broker-plugins.html"> |
| |
| |
| Broker Plugins |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.53" data-path="resource-limits.html"> |
| |
| <a href="resource-limits.html"> |
| |
| |
| Resource Limits |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.54" data-path="jms-bridge.html"> |
| |
| <a href="jms-bridge.html"> |
| |
| |
| The JMS Bridge |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.55" data-path="client-reconnection.html"> |
| |
| <a href="client-reconnection.html"> |
| |
| |
| Client Reconnection and Session Reattachment |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.56" data-path="diverts.html"> |
| |
| <a href="diverts.html"> |
| |
| |
| Diverting and Splitting Message Flows |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.57" data-path="core-bridges.html"> |
| |
| <a href="core-bridges.html"> |
| |
| |
| Core Bridges |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.58" data-path="transformers.html"> |
| |
| <a href="transformers.html"> |
| |
| |
| Transformers |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.59" data-path="duplicate-detection.html"> |
| |
| <a href="duplicate-detection.html"> |
| |
| |
| Duplicate Message Detection |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter active" data-level="1.60" data-path="clusters.html"> |
| |
| <a href="clusters.html"> |
| |
| |
| Clusters |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.61" data-path="federation.html"> |
| |
| <a href="federation.html"> |
| |
| |
| Federation |
| |
| </a> |
| |
| |
| |
| <ul class="articles"> |
| |
| |
| <li class="chapter " data-level="1.61.1" data-path="federation-address.html"> |
| |
| <a href="federation-address.html"> |
| |
| |
| Address Federation |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.61.2" data-path="federation-queue.html"> |
| |
| <a href="federation-queue.html"> |
| |
| |
| Queue Federation |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| |
| </ul> |
| |
| </li> |
| |
| <li class="chapter " data-level="1.62" data-path="ha.html"> |
| |
| <a href="ha.html"> |
| |
| |
| High Availability and Failover |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.63" data-path="connection-routers.html"> |
| |
| <a href="connection-routers.html"> |
| |
| |
| Connection Routers |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.64" data-path="graceful-shutdown.html"> |
| |
| <a href="graceful-shutdown.html"> |
| |
| |
| Graceful Server Shutdown |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.65" data-path="libaio.html"> |
| |
| <a href="libaio.html"> |
| |
| |
| Libaio Native Libraries |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.66" data-path="thread-pooling.html"> |
| |
| <a href="thread-pooling.html"> |
| |
| |
| Thread management |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.67" data-path="web-server.html"> |
| |
| <a href="web-server.html"> |
| |
| |
| Embedded Web Server |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.68" data-path="logging.html"> |
| |
| <a href="logging.html"> |
| |
| |
| Logging |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.69" data-path="embedding-activemq.html"> |
| |
| <a href="embedding-activemq.html"> |
| |
| |
| Embedding the Broker |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.70" data-path="karaf.html"> |
| |
| <a href="karaf.html"> |
| |
| |
| Apache Karaf |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.71" data-path="tomcat.html"> |
| |
| <a href="tomcat.html"> |
| |
| |
| Apache Tomcat |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.72" data-path="spring-integration.html"> |
| |
| <a href="spring-integration.html"> |
| |
| |
| Spring Integration |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.73" data-path="cdi-integration.html"> |
| |
| <a href="cdi-integration.html"> |
| |
| |
| CDI Integration |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.74" data-path="intercepting-operations.html"> |
| |
| <a href="intercepting-operations.html"> |
| |
| |
| Intercepting Operations |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.75" data-path="data-tools.html"> |
| |
| <a href="data-tools.html"> |
| |
| |
| Data Tools |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.76" data-path="activation-tools.html"> |
| |
| <a href="activation-tools.html"> |
| |
| |
| Activation Tools |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.77" data-path="maven-plugin.html"> |
| |
| <a href="maven-plugin.html"> |
| |
| |
| Maven Plugin |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.78" data-path="unit-testing.html"> |
| |
| <a href="unit-testing.html"> |
| |
| |
| Unit Testing |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.79" data-path="perf-tuning.html"> |
| |
| <a href="perf-tuning.html"> |
| |
| |
| Troubleshooting and Performance Tuning |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.80" data-path="perf-tools.html"> |
| |
| <a href="perf-tools.html"> |
| |
| |
| Performance Tools |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.81" data-path="configuration-index.html"> |
| |
| <a href="configuration-index.html"> |
| |
| |
| Configuration Reference |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.82" data-path="restart-sequence.html"> |
| |
| <a href="restart-sequence.html"> |
| |
| |
| Restart Sequence |
| |
| </a> |
| |
| |
| |
| </li> |
| |
| <li class="chapter " data-level="1.83" data-path="resource-adapter.html"> |
| |
| <a href="resource-adapter.html"> |
| |
| |
| Resource Adapter |
| |
| </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'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'll also discuss client side load balancing, where we can balance |
| client connections across the nodes of the cluster, and we'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'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'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"><<span class="hljs-name">broadcast-groups</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">broadcast-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-broadcast-group"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">local-bind-address</span>></span>172.16.9.3<span class="hljs-tag"></<span class="hljs-name">local-bind-address</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">local-bind-port</span>></span>5432<span class="hljs-tag"></<span class="hljs-name">local-bind-port</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">group-address</span>></span>231.7.7.7<span class="hljs-tag"></<span class="hljs-name">group-address</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">group-port</span>></span>9876<span class="hljs-tag"></<span class="hljs-name">group-port</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">broadcast-period</span>></span>2000<span class="hljs-tag"></<span class="hljs-name">broadcast-period</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>netty-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">broadcast-group</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">broadcast-groups</span>></span> |
| </code></pre> |
| <p>Some of the broadcast group parameters are optional and you'll normally |
| use the defaults, but we specify them all in the above example for |
| clarity. Let'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"><<span class="hljs-name">broadcast-groups</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">broadcast-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-broadcast-group"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">broadcast-period</span>></span>2000<span class="hljs-tag"></<span class="hljs-name">broadcast-period</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">jgroups-file</span>></span>test-jgroups-file_ping.xml<span class="hljs-tag"></<span class="hljs-name">jgroups-file</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">jgroups-channel</span>></span>activemq_broadcast_channel<span class="hljs-tag"></<span class="hljs-name">jgroups-channel</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>netty-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">broadcast-group</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">broadcast-groups</span>></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. |
| The typical location for the file is the <code>etc</code> directory from the broker instance.</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'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"><<span class="hljs-name">config</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span> |
| <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"urn:org:jgroups"</span> |
| <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">TCP</span> <span class="hljs-attr">bind_addr</span>=<span class="hljs-string">"${jgroups.bind_addr:site_local}"</span> |
| <span class="hljs-attr">bind_port</span>=<span class="hljs-string">"${jgroups.bind_port:7800}"</span> |
| <span class="hljs-attr">external_addr</span>=<span class="hljs-string">"${jgroups.external_addr}"</span> |
| <span class="hljs-attr">external_port</span>=<span class="hljs-string">"${jgroups.external_port}"</span> |
| <span class="hljs-attr">thread_pool.min_threads</span>=<span class="hljs-string">"0"</span> |
| <span class="hljs-attr">thread_pool.max_threads</span>=<span class="hljs-string">"200"</span> |
| <span class="hljs-attr">thread_pool.keep_alive_time</span>=<span class="hljs-string">"30000"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">RED</span>/></span> |
| |
| <span class="hljs-comment"><!-- a location that can be found by both server's running --></span> |
| <span class="hljs-tag"><<span class="hljs-name">FILE_PING</span> <span class="hljs-attr">location</span>=<span class="hljs-string">"../file.ping.dir"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">MERGE3</span> <span class="hljs-attr">min_interval</span>=<span class="hljs-string">"10000"</span> |
| <span class="hljs-attr">max_interval</span>=<span class="hljs-string">"30000"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">FD_SOCK2</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">FD_ALL3</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">"40000"</span> <span class="hljs-attr">interval</span>=<span class="hljs-string">"5000"</span> /></span> |
| <span class="hljs-tag"><<span class="hljs-name">VERIFY_SUSPECT2</span> <span class="hljs-attr">timeout</span>=<span class="hljs-string">"1500"</span> /></span> |
| <span class="hljs-tag"><<span class="hljs-name">BARRIER</span> /></span> |
| <span class="hljs-tag"><<span class="hljs-name">pbcast.NAKACK2</span> <span class="hljs-attr">use_mcast_xmit</span>=<span class="hljs-string">"false"</span> /></span> |
| <span class="hljs-tag"><<span class="hljs-name">UNICAST3</span> /></span> |
| <span class="hljs-tag"><<span class="hljs-name">pbcast.STABLE</span> <span class="hljs-attr">desired_avg_gossip</span>=<span class="hljs-string">"50000"</span> |
| <span class="hljs-attr">max_bytes</span>=<span class="hljs-string">"4M"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">pbcast.GMS</span> <span class="hljs-attr">print_local_addr</span>=<span class="hljs-string">"true"</span> <span class="hljs-attr">join_timeout</span>=<span class="hljs-string">"2000"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">UFC</span> <span class="hljs-attr">max_credits</span>=<span class="hljs-string">"2M"</span> |
| <span class="hljs-attr">min_threshold</span>=<span class="hljs-string">"0.4"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">MFC</span> <span class="hljs-attr">max_credits</span>=<span class="hljs-string">"2M"</span> |
| <span class="hljs-attr">min_threshold</span>=<span class="hljs-string">"0.4"</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">FRAG2</span> <span class="hljs-attr">frag_size</span>=<span class="hljs-string">"60K"</span> /></span> |
| <span class="hljs-comment"><!--RSVP resend_interval="2000" timeout="10000"/--></span> |
| <span class="hljs-tag"><<span class="hljs-name">pbcast.STATE_TRANSFER</span>/></span> |
| <span class="hljs-tag"></<span class="hljs-name">config</span>></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 |
| "jgroups-stacks.xml" then your <code>jgroups-file</code> should be like</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">jgroups-file</span>></span>jgroups-stacks.xml<span class="hljs-tag"></<span class="hljs-name">jgroups-file</span>></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'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's look at an example:</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">discovery-groups</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">discovery-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-discovery-group"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">local-bind-address</span>></span>172.16.9.7<span class="hljs-tag"></<span class="hljs-name">local-bind-address</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">group-address</span>></span>231.7.7.7<span class="hljs-tag"></<span class="hljs-name">group-address</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">group-port</span>></span>9876<span class="hljs-tag"></<span class="hljs-name">group-port</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">refresh-timeout</span>></span>10000<span class="hljs-tag"></<span class="hljs-name">refresh-timeout</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">discovery-group</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">discovery-groups</span>></span> |
| </code></pre> |
| <p>We'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 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"><<span class="hljs-name">discovery-groups</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">discovery-group</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-broadcast-group"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">jgroups-file</span>></span>test-jgroups-file_ping.xml<span class="hljs-tag"></<span class="hljs-name">jgroups-file</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">jgroups-channel</span>></span>activemq_broadcast_channel<span class="hljs-tag"></<span class="hljs-name">jgroups-channel</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">refresh-timeout</span>></span>10000<span class="hljs-tag"></<span class="hljs-name">refresh-timeout</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">discovery-group</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">discovery-groups</span>></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't mix |
| them!</p> |
| </blockquote> |
| <h4 id="discovery-groups-on-the-client-side">Discovery Groups on the Client Side</h4> |
| <p>Let'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'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'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'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'll look at both these cases in |
| turn with some examples, but first we'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'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"><<span class="hljs-name">cluster-connections</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-cluster"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">address</span>></span><span class="hljs-tag"></<span class="hljs-name">address</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>netty-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">check-period</span>></span>1000<span class="hljs-tag"></<span class="hljs-name">check-period</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connection-ttl</span>></span>5000<span class="hljs-tag"></<span class="hljs-name">connection-ttl</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">min-large-message-size</span>></span>50000<span class="hljs-tag"></<span class="hljs-name">min-large-message-size</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">call-timeout</span>></span>5000<span class="hljs-tag"></<span class="hljs-name">call-timeout</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">retry-interval</span>></span>500<span class="hljs-tag"></<span class="hljs-name">retry-interval</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">retry-interval-multiplier</span>></span>1.0<span class="hljs-tag"></<span class="hljs-name">retry-interval-multiplier</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">max-retry-interval</span>></span>5000<span class="hljs-tag"></<span class="hljs-name">max-retry-interval</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">initial-connect-attempts</span>></span>-1<span class="hljs-tag"></<span class="hljs-name">initial-connect-attempts</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">reconnect-attempts</span>></span>-1<span class="hljs-tag"></<span class="hljs-name">reconnect-attempts</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">use-duplicate-detection</span>></span>true<span class="hljs-tag"></<span class="hljs-name">use-duplicate-detection</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">message-load-balancing</span>></span>ON_DEMAND<span class="hljs-tag"></<span class="hljs-name">message-load-balancing</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">max-hops</span>></span>1<span class="hljs-tag"></<span class="hljs-name">max-hops</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">confirmation-window-size</span>></span>32000<span class="hljs-tag"></<span class="hljs-name">confirmation-window-size</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">call-failover-timeout</span>></span>30000<span class="hljs-tag"></<span class="hljs-name">call-failover-timeout</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">notification-interval</span>></span>1000<span class="hljs-tag"></<span class="hljs-name">notification-interval</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">notification-attempts</span>></span>2<span class="hljs-tag"></<span class="hljs-name">notification-attempts</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">discovery-group-ref</span> <span class="hljs-attr">discovery-group-name</span>=<span class="hljs-string">"my-discovery-group"</span>/></span> |
| <span class="hljs-tag"></<span class="hljs-name">cluster-connection</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">cluster-connections</span>></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'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. "europe" and "europe.news" 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>'eu' |
| matches all addresses starting with 'eu'</li> |
| <li>'!eu' |
| matches all address except for those starting with 'eu'</li> |
| <li>'eu.uk,eu.de' |
| matches all addresses starting with either 'eu.uk' or |
| 'eu.de'</li> |
| <li>'eu,!eu.uk' |
| matches all addresses starting with 'eu' but not those |
| starting with 'eu.uk'</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 four values - <code>OFF</code>, <code>STRICT</code>, <code>OFF_WITH_REDISTRIBUTION</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'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>If this is set to <code>OFF_WITH_REDISTRIBUTION</code> then like with 'OFF' messages |
| won't be initially routed to other nodes in the cluster. However, if <a href="#message-redistribution">redistribution</a> |
| is configured, it can forward messages in the normal way. In this way local consumers |
| will always have priority.</p> |
| <p>Keep in mind that this message forwarding/balancing is what we call |
| "initial distribution." It is different than <em>redistribution</em> which |
| is <a href="#message-redistribution">discussed below</a>.</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'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's by default is 1MB.</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"><<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-cluster"</span>></span> |
| ... |
| <span class="hljs-tag"><<span class="hljs-name">static-connectors</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>server0-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>server1-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">static-connectors</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">cluster-connection</span>></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"><<span class="hljs-name">cluster-user</span>></span>ACTIVEMQ.CLUSTER.ADMIN.USER<span class="hljs-tag"></<span class="hljs-name">cluster-user</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">cluster-password</span>></span>CHANGE ME!!<span class="hljs-tag"></<span class="hljs-name">cluster-password</span>></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 "clumped" 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><connection-load-balancing-policy-class-name></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><connection-load-balancing-policy-class-name></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><connection-load-balancing-policy-class-name></code>.</p> |
| </li> |
| <li><p>First Element. With this policy the "first" (i.e. 0th) node is |
| always returned.</p> |
| <p>Use |
| <code>org.apache.activemq.artemis.api.core.client.loadbalance.FirstElementConnectionLoadBalancingPolicy</code> |
| as the <code><connection-load-balancing-policy-class-name></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'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"><<span class="hljs-name">cluster-connection</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"my-cluster"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">address</span>/></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>netty-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">retry-interval</span>></span>500<span class="hljs-tag"></<span class="hljs-name">retry-interval</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">use-duplicate-detection</span>></span>true<span class="hljs-tag"></<span class="hljs-name">use-duplicate-detection</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">message-load-balancing</span>></span>STRICT<span class="hljs-tag"></<span class="hljs-name">message-load-balancing</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">max-hops</span>></span>1<span class="hljs-tag"></<span class="hljs-name">max-hops</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">static-connectors</span> <span class="hljs-attr">allow-direct-connections-only</span>=<span class="hljs-string">"true"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>server1-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">static-connectors</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">cluster-connection</span>></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't be forwarded to nodes which don't have matching |
| consumers. This is great and ensures that messages aren't moved to a |
| queue which has no consumers to consume them. However, there is a |
| situation it doesn'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'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 or consumers |
| with filters that don't match messages. The messages are re-routed 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> or <code>OFF_WITH_REDISTRIBUTION</code></p> |
| <p>Message redistribution can be configured to kick in immediately after |
| the need to redistribute is detected, or to wait a configurable delay 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-settings.html">Configuring Addresses and Queues via Address Settings</a>.</p> |
| <p>Here'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"><<span class="hljs-name">address-settings</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">address-setting</span> <span class="hljs-attr">match</span>=<span class="hljs-string">"#"</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">redistribution-delay</span>></span>0<span class="hljs-tag"></<span class="hljs-name">redistribution-delay</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">address-setting</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">address-settings</span>></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 |
| between detecting the need for redistribution and actually attempting redistribution. |
| 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'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't want to |
| redistribute immediately since the new consumer will arrive shortly.</p> |
| <h2 id="cluster-topologies">Cluster topologies</h2> |
| <p>Apache ActiveMQ Artemis clusters can be connected together in many different |
| topologies, let'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'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're only moving messages from node |
| A->B->C and never from C->B->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>To enable this behavior configure <code>scale-down</code> in the <code>live-only</code> |
| <code>ha-policy</code>, e.g.:</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">ha-policy</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">enabled</span>></span>true<span class="hljs-tag"></<span class="hljs-name">enabled</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">discovery-group-ref</span> <span class="hljs-attr">discovery-group-name</span>=<span class="hljs-string">"my-discovery-group"</span>/></span> |
| <span class="hljs-tag"></<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">ha-policy</span>></span> |
| </code></pre> |
| <p>If <code>scale-down</code>/<code>enabled</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>The <em>target</em> of the scale down operation can be configured a few differnt |
| ways. The above example uses <code>discovery-group-ref</code> to reference a |
| <code>discovery-group</code> which will be used to find the target broker. This |
| should be the same <code>discovery-group</code> referenced by your <code>cluster-connection</code>. |
| You can also specify a static list of <code>connector</code> elements, e.g.:</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">connectors</span>></span> |
| ... |
| <span class="hljs-tag"><<span class="hljs-name">connector</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"server0-connector"</span>></span>tcp://server0:61616<span class="hljs-tag"></<span class="hljs-name">connector</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">connectors</span>></span> |
| ... |
| <span class="hljs-tag"><<span class="hljs-name">ha-policy</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">enabled</span>></span>true<span class="hljs-tag"></<span class="hljs-name">enabled</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connectors</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">connector-ref</span>></span>server0-connector<span class="hljs-tag"></<span class="hljs-name">connector-ref</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">connectors</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">ha-policy</span>></span> |
| </code></pre> |
| <p>It's also possible to specify <code>group-name</code>. If this is specified then |
| messages will only be sent to another node in the cluster that uses the |
| same <code>group-name</code> as the server being shutdown, e.g.:</p> |
| <pre><code class="lang-xml"><span class="hljs-tag"><<span class="hljs-name">ha-policy</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">enabled</span>></span>true<span class="hljs-tag"></<span class="hljs-name">enabled</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">group-name</span>></span>my-group<span class="hljs-tag"></<span class="hljs-name">group-name</span>></span> |
| <span class="hljs-tag"><<span class="hljs-name">discovery-group-ref</span> <span class="hljs-attr">discovery-group-name</span>=<span class="hljs-string">"my-discovery-group"</span>/></span> |
| <span class="hljs-tag"></<span class="hljs-name">scale-down</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">live-only</span>></span> |
| <span class="hljs-tag"></<span class="hljs-name">ha-policy</span>></span> |
| </code></pre> |
| <blockquote> |
| <p><strong>Warning</strong></p> |
| <p>If cluster nodes are grouped together with different |
| <code>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> |
| |
| |
| </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.60","depth":1,"next":{"title":"Federation","level":"1.61","depth":1,"path":"federation.md","ref":"federation.md","articles":[{"title":"Address Federation","level":"1.61.1","depth":2,"path":"federation-address.md","ref":"federation-address.md","articles":[]},{"title":"Queue Federation","level":"1.61.2","depth":2,"path":"federation-queue.md","ref":"federation-queue.md","articles":[]}]},"previous":{"title":"Duplicate Message Detection","level":"1.59","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,"ignoreSpecialCharacters":false},"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":{},"version":"2.28.0","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":"2023-02-03T20:07:27.685Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2023-02-03T20:11:28.081Z"},"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> |
| |