## Dynamic Discovery Protocol

### Overview

The dynamic discovery protocol combines reconnect logic with the capability to auto-discover broker endpoints in the local network. The discovery protocol invokes a discovery agent in order to build up a list of broker URIs. The protocol then randomly chooses a URI from the list and attempts to establish a connection to it. If it does not succeed, or if it subsequently fails, a new connection is established to one of the other URIs in the list.

### Discovery agents

A discovery agent is a bootstrap mechanism that enables a message broker, consumer, or producer to obtain a list of broker URIs, where the URIs represent connector endpoints. The broker, consumer, or producer can subsequently connect to one of the URIs in the list.

The following kinds of discovery agent are currently supported in FUSE Message Broker:

- Simple (static) discovery agent.

- Multicast discovery agent.

- Rendezvous discovery agent.

For more details, see Discovery Agents .

### Configuring a transport connector with a discovery agent

Before you can use the discovery protocol, you must make your broker’s endpoints discoverable by adding a discovery agent to each transport connector. For example, to make a TCP transport connector discoverable, set the `discoveryUri` attribute on the `transportConnector` element as follows:

        <transportConnectors>
            <transportConnector
                name="openwire" uri="tcp://localhost:61716" discoveryUri="multicast://default"/>
        </transportConnectors>

Where the TCP transport connector is configured to use the multicast discovery agent, `multicast://default`.

### Configuration syntax

A `discovery` URI must conform to the following syntax:

    discovery://(DiscoveryAgentUri)?TransportOptions

Where the discovery agent URI, `DiscoveryAgentUri`, identifies a discovery agent, as described in Discovery agents above. The transport options, `?``TransportOptions`, are specified in the form of a query list (where the supported options are described in Table 6.2 ). If no transport options are required, you can use the following alternative syntax:

    discovery://DiscoveryAgentUri

### Transport options

The discovery protocol supports the transport options described in Table 6.2

Table 6.2. Discovery Transport Options

Option Name | Default | Description
--- | --- | ---
`initialReconnectDelay` | `10` | How long to wait before the first reconnect attempt (in ms).
`maxReconnectDelay` | `30000` | The maximum amount of time to wait between reconnect attempts (in ms).
`useExponentialBackOff` | `true` | If `true`, use an exponential back-off between reconnect attempts.
`backOffMultiplier` | `2` | The exponent used in the exponential back-off algorithm.
`maxReconnectAttempts` | `0` | If not `0`, this is the maximum number of reconnect attempts before an error is sent back to the client.

### Sample URI

The following is an example of a discovery URI that uses a multicast discovery agent:

    discovery://(multicast://default)?initialReconnectDelay=100

### Example of using the dynamic discovery protocol

To try out the dynamic discovery protocol, perform the following steps:

1. Configure the brokers’ transport connectors .

2. Start up broker A .

3. Start up consumer A .

4. Start up broker B .

5. Start up consumer B .

6. Start up a producer with discovery URL .

7. Kill the active broker

### Configure the brokers’ transport connectors

To run the current example you need a cluster of two brokers: broker A and broker B. For details of how to set up the broker cluster, see Configuring a Simple Broker Cluster . In particular, you must ensure that each broker configures its TCP transport connector with a discovery URI, as follows:

        <transportConnectors>
            <transportConnector
                name="openwire" uri="tcp://localhost:61716" discoveryUri="multicast://default"/>
        </transportConnectors>

Where the `discoveryUri` attribute on the `transportConnector` element is initialized to `multicast://default`.

### Start up broker A

Assuming that you have already configured a simple broker cluster as described in Configuring a Simple Broker Cluster , start broker A by running the relevant script. For example:

    broker_a

### Start up consumer A

Start a consumer that consumes messages from the `TEST.FOO` queue on broker A. Assuming that broker A’s TCP connector is listening on port `61716` on the local host, open a new command window and start consumer A as follows:

    cd InstallDir/example
    ant consumer -Durl=tcp://localhost:61716 -Dmax=100

### Start up broker B

Start broker B by running the relevant script. For example, open a new command window and enter:

    broker_b

### Start up consumer B

Start a consumer that consumes messages from the `TEST.FOO` queue on broker B. Assuming that broker B’s TCP connector is listening on port `61816` on the local host, open a new command window and start consumer B as follows:

    cd InstallDir/example
    ant consumer -Durl=tcp://localhost:61816 -Dmax=100

### Start up a producer with discovery URL

Start a producer with a discovery URL such that it can connect either to broker A or to broker B. Open a new command window and start the producer as follows:

    cd InstallDir/example
    ant producer -Durl=discovery://(multicast://default) -DsleepTime=2000

The sleep time is set to 2 seconds between messages, in order to give you enough time to perform the next step.

As the producer starts up, it should log the following lines to the screen:

    Buildfile: build.xml
    init:
    compile:
    producer:
         [echo] Running producer against server at $url = discovery://(multicast://default)
    for subject $subject = TEST.FOO
         [java] Connecting to URL: discovery://(multicast://default)
         [java] Publishing a Message with size 1000 to queue: TEST.FOO
         [java] Using non-persistent messages
         [java] Sleeping between publish 2000 ms
         [java] 16:27:55 WARN  brokerName not set
         [java] 16:27:56 INFO  Adding new broker connection URL: tcp://fboltond820:61816
         [java] 16:27:56 INFO  Adding new broker connection URL: tcp://fboltond820:61716
         [java] 16:27:56 INFO  Successfully reconnected to tcp://fboltond820:61816

You can ignore the warning message, `WARN brokerName not set`. The next two `INFO` messages show that the discovery mechanism is working: each of the discovered URLs is logged here. Finally, the producer connects to one of the discovered URLs and starts sending message to that broker.

### Kill the active broker

After starting the producer, observe which of the consumers is receiving messages. If consumer A is receiving messages, the producer must be connected to broker A, in which case broker A is the active broker. If consumer B is receiving messages, broker B is the active broker.

To test the failover functionality on the producer side, kill the active broker (not consumer!) by switching focus to the relevant broker window and typing `Ctrl-C`. If the producer is still producing messages, it will attempt to reconnect to the other broker. You should see output similar to the following in the producer log:

         [java] 16:28:10 WARN  Transport failed, attempting to automaticallyreconnect due to: java.io.EOFException
         [java] java.io.EOFException
         [java]     at java.io.DataInputStream.readInt(DataInputStream.java:358) ...
         [java] Sending message: Message: 7 sent at: Wed Oct 10 13:50:31 BST 2007  ...
         [java] 16:28:10 INFO  Successfully reconnected to tcp://fboltond820:61716