A network of brokers creates a cluster composed of multiple ActiveMQ instances that are interconnected to meet more advanced messaging scenarios. Various topologies for broker networks, their purpose, and their configuration details are explained in detail in chapter 10. The previous section discussed transport connectors that provide client-to-broker communications, whereas this section will discuss network connectors that provide broker-to-broker communications.
Network connectors are channels that are configured between brokers so that those brokers can communicate with one another. A network connector is a unidirectional channel by default. A given broker communicates in one direction by only forwarding messages it receives to the brokers on the other side of the connection. This setup is commonly referred to as a forwarding bridge. In some situations, you may want to create a bidirectional communication channel between brokers—a channel that communicates not only outward to the brokers on the other side of the connection, but also receives messages from other brokers on that same channel. ActiveMQ supports this kind of bidirectional connector, which is usually referred to as a duplex connector. Figure 4.5 shows one example of a network of brokers that contains both a forwarding bridge and duplex connectors.
Network connectors are configured through the ActiveMQ XML configuration file in a fashion similar to the configuration of transport connectors. Let’s take a look at an example configuration:
In the rest of this chapter, various ActiveMQ protocols and techniques that are used to configure and connect to a network of brokers will be presented and discussed. But before we dive in, there’s one more important ActiveMQ concept we should explain known as discovery. In general, discovery is a process of detecting remote broker services. Clients usually want to discover all available brokers. Brokers, on the other hand, usually want to find other available brokers so they can establish a network of brokers.
When you want to configure a network of brokers, the first obvious question is, do you know the exact network address of each broker in the network? If the answer is yes, then you can proceed configuring your network statically and also connect your clients to predefined broker URIs. This situation is more often seen in production environments where you want to have total control of all resources. Next section (Section 4.5.1) explains how you can set up and use static networks. It starts with explaining the static protocol used to connect multiple brokers together. Then, we’ll explain a failover protocol that allows clients to connect to one of the brokers in the network and also utilize reconnection logic.
In case clients and brokers don’t know each other’s network addresses, they must use some kind of a discovery mechanism to dynamically locate the available brokers. This kind of setup is more often found in development environments, as it’s much easier to set up and maintain. Discovery agents and the protocols they use are explained in section 4.5.2. You’ll learn how IP multicast is used by brokers to advertise their services and locate other available brokers, using themulticast connector. Also, we’ll see how clients use the multicast connector to discover brokers using a discovery connector.
We’ll also dive into the peer connector, which makes creating a network of embedded brokers a very simple task. Finally, we’ll see how the fanout connectorenables clients to send messages to multiple brokers. Let’s begin with static networks.
The first approach to configuring and connecting to a network of brokers is through the use of statically configured URIs—configuring a list of broker URIs available for connection. The only prerequisite is that you know the addresses of all the brokers you want to use. Once you have these URIs, you need to know how to use them in a configuration. So let’s look at the connector available to create a static networks of brokers.
The static network connector is used to create a static configuration of multiple brokers in a network. This protocol uses a composite URI—a URI that contains other URIs. A composite URI consists of multiple broker addresses or URIs that are on the other end of the network connection.
Here’s the URI syntax for the static protocol:
You can find the complete reference for this transport at the ActiveMQ website (http://mng.bz/r74v).
Now take a look at the following configuration example:
The output indicates that the broker on the localhost has successfully configured a forwarding bridge with two other brokers running on two remote hosts. In other words, messages sent to the local broker will be forwarded to brokers running on remotehost1 and remotehost2, but only if there’s demand for those messages from a consumer.
The best way to understand this is to walk through the use of static networks using the stock portfolio example with a network of brokers. Figure 4.6 provides a perspective of the broker topology used in this example.
In the diagram, the two brokers are networked. The brokers utilize a network connector with a URI using the static protocol. A consumer is attached to a destination on BrokerB, which creates demand for messages across the network connector. When the producer sends messages to the same destination on BrokerA, they’ll be forwarded to the broker where there’s demand. In this case, BrokerA forwards messages to BrokerB. The following example will walk through this basic use case.
To make this example work, first we need to start these two networked brokers. Let’s start with BrokerB:
Now it's time to configure BrokerA:
Now that we have both brokers up and running, let’s run the stock portfolio example. First we’ll start our publisher and connect it to BrokerA:
This is practically the same command was used with the earlier TCP connector example. Now start the consumer and connect it to BrokerB:
Using this setup, messages are published to BrokerA. These messages are then forwarded to BrokerB, where they’re received by the consumer. The overall functionality of this example hasn’t been changed and both the publisher and the consumer behave the same as the previous single broker example. The only difference is that the publisher and the consumer are now connecting to different brokers that are networked using the static protocol.
From this simple example you can conclude that this particular configuration can help you in situations when you need your distributed clients to benefit from the performance advantages of communicating with the local broker instead of a remote one.
EXAMPLE USE OF THE STATIC PROTOCOL
Configuring broker networks can be difficult depending on the situation. Use of the static protocol allows for an explicit notation that a network should exist. Consider a situation where clients in remote offices are connecting to a broker in the home office. Depending on the number of clients in each remote office, you may wind up with far too many wide area network connections into the home office. This can cause an unnecessary burden on the network. To minimize connections, you may want to place a broker in each remote office and allow a static network connection between the remote office broker and the home office broker. Not only will this minimize the number of network connections between the remote offices and the home office, but it’ll allow the client applications in the remote offices to operate more efficiently. The removal of the long haul connection over the wide area network means less latency and therefore less waiting for the client application.
In all the examples so far, the clients have been configured to connect to only one specific broker. But what should you do in case you can’t connect to the desired broker or your connection fails at the later stage? Your clients have two options: either they’ll die gracefully or try to connect to the same or some other broker and resume their work. As you can probably guess, the stock portfolio example runs using the protocols described thus far and aren’t immune to network problems and unavailable brokers. That’s where protocols such as failover come in to implement automatic reconnection. Similar to the case with the network connectors, there are two ways to provide a list of suitable brokers to which the client can connect. In the first case, you
provide a static list of available brokers. This is the approach used by the failover transport connector. In the second case, dynamic discovery of the available brokers is used. This will be explained later in the chapter. This section will examine the failover transport connector.
The URI syntax for the failover connector is similar to the previous static network connector URI. There are actually two available forms to the failover URI:
The complete reference of this protocol can be found at the ActiveMQ website (http://mng.bz/u58s).
By default, this protocol uses a random algorithm to choose one of the underlying connectors. If the connection fails (both on startup or at a later stage), the transport will pick another URI and try to make a connection. A default configuration also implements reconnection delay logic, meaning that the transport will start with a 10ms delay for the first reconnection attempt and double this time for any subsequent attempt up to 30000ms. Also, the reconnection logic will try to reconnect indefinitely. Of course, all reconnection parameters can be reconfigured according to your needs using the appropriate transport options.
Recall the theoretical static network of brokers that was defined in the previous section. In that example, all messages sent to the local broker could be forwarded to the brokers located on remotehost1 and remotehost2. Because all messages could be sent to both of these brokers, those messages can be consumed from either broker. The same is true here. The only difference is that the failover transport will automatically attempt a reconnect in the event of a broker failover. To experience the use of this transport, run the stock portfolio consumer and configure it to connect to the brokers using the failover connector:
The beauty of this solution is that it requires no changes to the application in order to add support for automatic reconnection in the event of a broker failure.
Now let’s see the failover connector at work. Imagine that the random algorithm in the failover transport has chosen to connect the consumer to the broker onhost1. You can expect that the consumer will print the following log message during the startup:
As we already said, all messages sent by the publisher to the local broker will be forwarded to the broker on host1 and received by the consumer. Now try to simulate a broker failure by shutting down the broker on host1. The consumer will print the following log message:
The consumer has successfully connected to the other broker and you can see that it resumed its normal operation without any assistance.
EXAMPLE USE OF THE FAILOVER PROTOCOL
Due to its reconnection capabilities, it’s highly advisable that you use the failover protocol for all clients, even if a client will only be connecting to a single broker. For example, the following URI will try to reestablish a connection to the same broker in the event that the broker shuts down for any reason:
The advantage of this is that clients don’t need to be manually restarted in the case of a broker failure (or maintenance, and so forth). As soon as the broker becomes available again the client will automatically reconnect. This means far more robustness for your applications by simply utilizing a feature of ActiveMQ. The failover transport connector plays an important role in achieving advanced functionalities such as high availability and load balancing as will be explained inchapter 12.