## 10.2 ActiveMQ如何在代理网络间 传送消息

### 10.2 How ActiveMQ passes messages across a network of brokers

ActiveMQ supports the concept of linking ActiveMQ message brokers together into  different topologies, or networks of brokers as they’re known. Often it’s a requirement  that geographically dispersed applications need to communicate in a reliable way.

### 10.2 ActiveMQ 如何在代理网络间 传送消息

ActiveMQ支持将ActiveMQ消息代理链接起来组成不同的拓扑结构,或者组成彼此互通的代理网络.  通常,地理上分散的应用程序彼此间进行可靠的通信是一个需求.

This is a situation where having a centralized broker architecture into which all the clients  connect isn’t the optimal messaging paradigm.

Through the rest of this section, the ActiveMQ store and forward concept will be  examined in detail. We’ll look at how brokers discover each other in a network and  how to configure an ActiveMQ broker to cooperate in a network.

#### 10.2.1 Store and forward

ActiveMQ networks  use the  concept of  store and  forward, whereby messages are  always stored in the local broker  before being forwarded across the network  to  another  broker.  This  means  that  if  messages  can’t  be  delivered  due to  connectivity issues, when the connection is reestablished, a broker will be able  to send  any undelivered  messages across  the network  connection to the remote  broker.  By default,  a network  only operates  in a  unidirectional manner  and  logically pushes  messages across  its network  connection, as  shown in  figure  10.4.

#### 10.2.1 消息存储和转发

ActiveMQ代理网络使用存储和转发的概念,即,消息通常被存储在本地代理中,然后才通过网络  转发到其他代理.这就是说,如果因为网络连接问题导致消息不能被及时投送,那么当网络连接  恢复并重建后,代理可以重新发送任何未及时投送的消息到远程代理上.默认情况下,如图10.4  所示,一个消息网络仅以单向方式在通过逻辑上的网络中推送消息.

When a network is established from a local broker to a remote broker, the remote  broker will pass information containing all its durable and active consumers’ destinations  to the local broker. The local broker uses this information to determine what  messages the remote broker is interested in and forward them to the remote broker.  It’s possible to define filters on the network connection and to always include or  exclude messages for a particular destination—we’ll cover this in the configuration  section later in this chapter.

Having networks operate in one direction allows for networks to be configured for  message passing in a one-way fashion. If you want networks to be bidirectional, you  can either configure the remote broker with a network connector to point to the local  broker, or configure a network connector to be duplex so it sends messages in both  directions.

Suppose you have a deployment scenario where you have many supermarkets that  need to connect to a back office order system. It would be hard to configure new  supermarkets and inflexible for the broker(s) at the back office to be aware of all the  remote brokers in each new supermarket. Typically the back office brokers would be  located behind a firewall with only a limited number of ports open to accept connections  inward, as depicted in figure 10.5.

The diagram of the supermarket broker in figure 10.5 requires that the network connector  be configured in duplex mode. The single network connection, established  from the supermarket broker to the back office, would be able to pass messages in  both directions and would behave in the same way as if the back office broker had  established a normal network connection back to the supermarket broker.

The configuration for the supermarket broker would include configuration for the  network connector that would look something like the following.
Listing 10.1 Configuring a store network broker

<networkConnectors>
<networkConnector
uri="static://(tcp://backoffice:61617)"
name="bridge"
duplex="true" <!-- 这样远程代理也建立和本地代理的连接 -->
conduitSubscriptions="true"
decreaseNetworkConsumerPriority="false">
</networkConnector>
</networkConnectors>

Please be aware that the order in which you specify the network connections and the persistence you use in the ActiveMQ broker configuration is important. Always configure networks, persistence, and transports in the following order:
1 Networks—They need to be established before the message store.
2 Message store—Should be configured before transports.
3 Transports—Should be the last in the broker configuration.

1 网络连接 — 网络练剑需要在消息存储之前建立好
2 消息存储 — 需要在传输连接之前配置
3 传输连接 — 应当是代理配置后最后配置

An example broker configuration in the correct order is shown next.
Listing 10.2 An example of the correct broker configuration order

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://activemq.apache.org/schema/core">

<networkConnectors>
<networkConnector uri="static:(tcp://backoffice:61617)"/>
</networkConnectors>

<transportConnectors>
<transportConnector uri="tcp://localhost:62002"/>
</transportConnectors>

</broker>
</beans>

In large deployment scenarios, it makes sense to combine high availability and network  configurations, as shown in figure 10.6.

In this scenario, the local master and slave brokers both need to be configured to create  network connections to both the remote master and the slave to cater to the possibility  of the remote master failing. Only when a slave becomes active (becomes the  new master) will it start its transports and network connections.

If a network can’t establish a connection to a remote broker (as in the case of a  remote slave), or the network connection fails, the network will poll the connection  until it can establish a connection.

如果不能建立到远程代理的连接(因为远程代理是一个备机代理),或者网络连接失效,那么  该网络将不断尝试连接,直到它可以建立一个连接。

In this section you’ve seen how store and forward works, as well as message passing  over networks, with an example use case of supermarkets communicating with their  back office systems. In the next section, we’ll look at how brokers in a network discover  each other.

#### 10.2.2 Network discovery

When a network connection is established to a remote broker, that connection uses a discovery agent to locate the remote broker and (re-)establish that connection. Two main types of network discovery are provided with ActiveMQ:

1 Dynamic—Searches for brokers using multicast or rendezvous
2 Static—Configured with list of broker URLs with which to establish a connection

#### 10.2.2 网络侦测

ActiveMQ提供两种类型的网络侦测:
1 动态网络 — 使用多点传送与会合协议
2 静态网络 — 使用一系列的静态的代理URL来建立连接

Using multicast discovery to create network connections is straightforward. When you  start an ActiveMQ broker with a multicast transport on a network connector, it will  search for another broker using IP multicast and establish a connection. A network  configuration for multicast discovery is shown in the following listing.
Listing 10.3 A network connector using multicast

<networkConnectors>
<networkConnector uri="multicast://default"/>
</networkConnectors>

The default name in the multicast:// URI denotes the group to which the broker  belongs. When using multicast discovery, it’s strongly recommended that you use a  unique group name so that your brokers don’t connect to other application brokers  unbeknownst to you. Not only can this lead to surprising results, but you can spend a  great deal of time chasing a red herring!

multicast://URI中的default表示该代理所属的群组名称.在使用多点传送侦测时,强烈建议使用唯一的   群组名称,这样你的代理就不会在你不知道的情况下去连接其他应用程序的代理.尽管这个配置会产生令人惊讶   的结果,你仍然需要花一些时间去看看与之相关的其他配置.

There are a couple of limitations with multicast discovery, including the ability to  control which brokers are discovered, and the fact that it’s usually restricted to the discovery  of brokers on the local network segment. This is because IP multicast doesn’t  extend through routers.

Most of the example configurations used previous to this chapter have used static  discovery for establishing networks. Although they require a little more configuration  and they wouldn’t be suitable for a large number of networks, they’re typically used  for most deployments. Static discovery accepts a list of broker URIs and will try to connect  to the remote brokers in the order they’re determined in the list.

For example, to configure the local master broker and the local slave broker to  connect to the remote master, but fail over to the remote slave (see figure 10.6), you’d  configure the local brokers as shown next.
Listing 10.4 An example network connector

<networkConnectors>
<networkConnector uri="static:(tcp://remote-master:61617,tcp://remote-slave:61617)"/>
</networkConnectors>

The static network discovery agent can be configured to control which frequency it  will try to reestablish a connection with on failure. The configuration properties for  the static transport are shown in table 10.3.

Table 10.3 Configuration properties for a static transport

Property name Default value Description
initialReconnectDelay  1000  The time in milliseconds before attempting to reconnect the network. This is only used if useExponentialBackOff isn’t enabled.
maxReconnectDelay 30000 The maximum time in milliseconds that the network will wait before trying to establish a connection after failure. This is only used if useExponentialBackOff is enabled.
useExponentialBackOff true If this is enabled, the network will increase the time to wait between each failed attempt to establish a connection.
backOffMultiplier 2 Used in conjunction with useExponentialBackOff, the multiplier to use to increase the time to wait between each new attempt to establish a network connection.

initialReconnectDelay  1000  重新建立连接之前等待的时间(毫秒).只在useExponentialBackOff 没有开启时有效.
maxReconnectDelay 30000 在网络连接失效后,尝试重新建立连接之前的等待时间.只在useExponentialBackOff启用时有效
useExponentialBackOff true 如果启用该参数,从连接失败到重建连接之间的等待时间将增长(即,本次连接失效与尝试重连之间的等待时间比上次长)
backOffMultiplier 2 与useExponentialBackOff联合使用,两次连接失效与重建连接之前 的 等待时间的增量

A network connection will always try to establish a connection to a remote broker, so  there’s no concept of just giving up! You can set the configuration options for the static  transport as part of the URI. An example of this is provided in the following listing.
Listing 10.5 An example of configuring the static transport

<networkConnectors>
<networkConnector uri="static:(tcp://remote:61617)?useExponentialBackOff=false"/>
</networkConnectors>

The multicast and the static discovery mechanisms are shown here, along with some  of the trade-offs between them. Many configuration options are available when setting  up networks in ActiveMQ; these will be reviewed in more detail in the next section.

#### 10.2.3 Network configuration

Networks by default rely on the remote broker to inform them when the broker  is  interested  in  their  local  messages.  For  existing  active  and  new message  consumers,  the  destination  to  which the  message  consumer  is  listening is  propagated  to  the  local  broker’s  network  connection.  The  local  network  connection  will  then  subscribe  on behalf  of  the  remote  broker’s message  consumers for messages to be forwarded across the network. In order for networks  to   function  properly   in  a   dynamic  environment,   the  broker   property  advisorySupport  needs  to  be  enabled (it’s  possible  to  have  a statically  configured network without enabling advisories). ActiveMQ uses advisory messages  to communicate state between  brokers (more on this  in chapter 14). Because  of  this, advisory messages are used  to forward information about changing  message  consumers across broker networks as well as clients.

#### 10.2.3 网络配置

There may not be any active durable subscribers or consumers for an existing destination  on the remote broker. So when the network connection is initialized to the  remote broker, the remote broker will read through its message store for existing destinations  and pass those to the local broker. Then the local broker can forward messages  for those destinations as well.

It’s important to note that a network will use the name of the broker to create a  unique durable subscription proxy on behalf of a remote broker. Hence, if at a later  point in time you change the name of the broker, you could lose messages over networks  for durable topic subscribers. To avoid this, make sure to use a unique name for  the brokerName attribute on the <broker> element. See the following for a brief  example.
Listing 10.6 Make sure to use unique names for the broker

<broker xmlns="http://activemq.apache.org/schema/core"
brokerName="brokerA"
...
<networkConnectors>
<networkConnector name="brokerA-to-brokerB" uri="tcp://remotehost:61616" />
</networkConnectors>
</broker>

With a basic understanding of how networks operate, you’ll be able to comprehend  some of the side effects if you change the default network configuration. A network  has several important configuration properties, in addition to the duplex property.

NETWORK PROPERTY: DYNAMICONLY

All networks are dynamic only in the sense that they depend on advisories. The  dynamicOnly option configures whether inactive durable subs are networked on a  restart; with dynamicOnly=true, a networked durable sub will not be enabled till it is  again activated. The dynamicOnly property is false by default.

DYNAMICONLY属性

NETWORK PROPERTY: PREFETCHSIZE

The prefetchSize effects message dispatch to forwarding consumers, but message  acknowledgement always uses INDIVIDUAL_ACK mode on each message receipt. The  default value for this property is 1000.

PREFETCHSIZE属性

prefetchSize属性影响消息分发到消息消费者,但是每个消息被接收时消息的确认模式通常使用INDIVIDUAL_ACK模式.prefetchSize属性默认值为1000.

NETWORK PROPERTY: CONDUITSUBSCRIPTIONS

An ActiveMQ message broker will send a copy of a message to every interested consumer  of which it’s aware, even across networks. But this can be a problem, as the  remote broker will send every message it receives to any of its interested consumers.  So it’s possible to end up with duplicate messages on the remote broker. The  conduitSubscriptions property is used to inform the network connection that it  should treat multiple matching destinations as a single destination to avoid this problem.  The conduitSubscriptions property is true by default.

CONDUITSUBSCRIPTIONS属性

ActiveMQ消息代理会将消息副本发送给该代理已感知到的每一个对消息感兴趣的消息消费者,即使这些消息消费者是 跨网络的.但是,这样会产生一个问题,因为远程代理会发送其接收到的所有消息给对消息感兴趣的消费者.因此,远程代理上可能收到重复的消息(译注:一个消息同时发送给好几个远程代理,而远程代理又将消息复制后发给彼此造成重复发送).conduitSubscriptions属性用来通知网络连接使用多目的地消息匹配代替单目的地消息匹配,已避免  消息重复发送问题.conduitSubscriptions默认值为true.

NETWORK PROPERTY: EXCLUDEDDESTINATIONS

You can tell the network to exclude certain destinations from passing messages across  a network. This property can be used, for example, to prevent destinations that  should only be used by local consumers from being propagated to a remote broker.  Excluded destinations are denoted inside of the <excludedDestinations> element as  either a <queue> or a <topic> element. Each one uses a physicalName attribute for  the name of the queue or topic to exclude. You can combine a list of excluded destinations,  and use wildcards to denote the names of the destinations to exclude, too.

EXCLUDEDDESTINATIONS属性

Excluded destinations take priority over both the <staticallyIncludedDestinations> element and   <dynamicallyIncludedDestinations> element. So if you  have matching destinations in either of those lists, they’ll be excluded. Here’s an example  configuration using the <excludedDestinations> element.
Listing 10.7 Creating a list of excluded destinations

<networkConnectors>
<networkConnector uri="static:(tcp://remote:61617)?useExponentialBackOff=false">
<excludedDestinations>
<queue physicalName="audit.queue-1"/>
<queue physicalName="audit.queue-2"/>
<queue physicalName="local.>"/>
<topic physicalName="local.>"/>
</excludedDestinations>
</networkConnector>
</networkConnectors>

NETWORK PROPERTY: DYNAMICALLYINCLUDEDDESTINATIONS

You can ask the network to only pass messages to the remote broker for active message  consumers that match the list of destinations for dynamicallyIncludedDestinations.  The format is the same as the excludedDestinations. An empty list denotes that all  messages will be passed to the remote broker, as long as they’re not in the excluded-Destinations list.

DYNAMICALLYINCLUDEDDESTINATIONS属性

NETWORK PROPERTY: STATICALLYINCLUDEDDESTINATIONS

You can ask the network to only pass messages to the remote broker if they match the  list of destinations for staticallyIncludedDestinations. The format is the same as  the excludedDestinations; an example is provided in the following listing.
Listing 10.8 Setting options for included destinations

STATICALLYINCLUDEDDESTINATIONS属性

<networkConnectors>
<networkConnector uri="static:(tcp://remote:61617)?useExponentialBackOff=false">
<staticallyIncludedDestinations>
<queue physicalName="management.queue-1"/>=
<queue physicalName="management.queue-2"/>
<queue physicalName="global.>"/>
<topic physicalName="global.>"/>
</staticallyIncludedDestinations>
</networkConnector>
</networkConnectors>

NETWORK PROPERTY: DECREASENETWORKCONSUMERPRIORITY

The decreaseNetworkConsumerPriority property influences the algorithm used to  determine which message consumer for a queue should receive the next dispatched  message. When enabled, it’ll give a network consumer the lowest priority, meaning  that messages from a local broker queue will only be sent to a remote broker if there  are no local consumers or they’re all busy. But the decrease in priority depends on the  broker path. For example, if a consumer is two hops away from the broker it will be  given the priority of –7, a consumer one hop away will be given the priority of –5, and  a local consumer will be given priority 0. The decreaseNetworkConsumerPriority  property is false by default.

DECREASENETWORKCONSUMERPRIORITY属性

decreaseNetworkConsumerPriority属性影响决定哪一个消息消费者将要接收下一批消息的算法.如果启用该参数,网络中消息消费者的优先级被调成最低,这样,只有在不存在本地消息消费者或者本地消息消费者都处于忙碌状态时,才会将本地队列中的消息发送到远程的消息消费者.但是,优先级下降的等级受到代理的网络路径的影响.比如,如果一个消息消费者离代理的网络跳度(从一个网络设备,一般为路由器到另一台为一跳,即1hop)为2个hop,则该消费者的优先级为-7,离代理的网络跳度为1个hop时,该消费者的优先级被设置为-5,并且本地消费者优先级为0.decreaseNetworkConsumerPriority的默认值为false.

NETWORK PROPERTY: NETWORKTTL

The networkTTL property denotes the maximum number of remote brokers a message  can pass through before being discarded. This is useful for ensuring messages  aren’t forwarded needlessly, if you have a cyclic network of connected brokers. The  default value for the networkTTL property is 1.

NETWORKTTL属性

networkTTL属性设置消息在被丢弃之前最多可以发送的远程代理的数量.假如你使用的是一个循环代理网络,  这个参数可以避免不必要的消息转发.networkTTL的默认值是1.

NETWORK PROPERTY: NAME

The default name for a network connector is bridge. It’s a good idea to give this property  a unique value when the broker is first configured, so it can be found easily  from JMX.

NAME属性

There are cases  when it makes  sense to have  more than one  network connection  between the same local and remote brokers. In this case, each connector requires  a unique name. So why have more than one network connection between the two same  brokers?  It comes  down to  performance. A  network connection  uses a  single  transport connection, and if you’re anticipating a heavy load across a network,  it makes sense  to have more  than one transport  connection. You do  need to be  careful  that you  don’t get  duplicate messages,  so you  have to  set up  the  network connections with the appropriate  filters. Using one for queues  and one  for topics  can often  improve throughput  for general  messaging use  cases, as  depicted in figure 10.7.
The corresponding configuration for figure 10.7 is shown next.
Listing 10.9 Setting options for included destinations

(译注:配置图10.7所示的的为同一个网配置两个网络连接,一个用来传送队列中消息,一个用于传送小子主题中消息)

<networkConnectors>

<networkConnector uri="static://(tcp://remotehost:61617)"name="queues_only" duplex="true">
<excludedDestinations>
<topic physicalName=">"/>
</excludedDestinations>
</networkConnector>

<networkConnector uri="static://(tcp://remotehost:61617)"name="topics_only"duplex="true">
<excludedDestinations>
<queue physicalName=">"/>
</excludedDestinations>
</networkConnector>
</networkConnectors>

Having looked at how networks operate and how to configure them, we can now use  this knowledge to help scale your ActiveMQ applications.

微信赞赏  支付宝赞赏