Chapter 8. Addresses, Queues, and Topics

AMQ Broker has a unique addressing model that is both powerful and flexible and that offers great performance. The addressing model comprises three main concepts: addresses, queues and routing types.

An address represents a messaging endpoint. Within the configuration, a typical address is given a unique name, 0 or more queues, and a routing type.

A queue is associated with an address. There can be multiple queues per address. Once an incoming message is matched to an address, the message is sent on to one or more of its queues, depending on the routing type configured. Queues can be configured to be automatically created and deleted.

A routing type determines how messages are sent to the queues associated with an address. A AMQ Broker address can be configured with two different routing types.

Table 8.1. Routing Types

If you want your messages routed to…​Use this routing type …​

A single queue within the matching address, in a point-to-point manner.

anycast

Every queue within the matching address, in a publish-subscribe manner.

multicast

Note

An address must have at least one routing type.

It is possible to define more than one routing type per address, but this typically results in an anti-pattern and is therefore not recommended.

If an address does use both routing types, however, and the client does not show a preference for either one, the broker typically defaults to the anycast routing type. The one exception is when the client uses the MQTT protocol. In that case, the default routing type is multicast.

8.1. Address and Queue Naming Requirements

You should be aware of the following requirements when you configure addresses and queues:

  • To ensure that a client can connect to a queue regardless of which wire protocol it uses, your address and queue names should not include any of the following characters:

    & :: , ? >

  • The # and * characters are reserved for wildcard expressions. For more information, see the section called “AMQ Broker Wildcard Syntax”.
  • Address and queue names should not include any spaces.
  • To separate words in an address or queue name, use the configured delimiter character (the default is the . character). For more information, see the section called “AMQ Broker Wildcard Syntax”.

8.2. Configuring Point-to-Point Messaging

Point-to-point messaging is a common scenario in which a message sent by a producer has only one consumer. AMQP and JMS message producers and consumers can make use of point-to-point messaging queues, for example. Define an anycast routing type for an address so that its queues receive messages in a point-to-point manner.

When a message is received on an address using anycast, AMQ Broker locates the queue associated with the address and routes the message to it. When consumers request to consume from the address, the broker locates the relevant queue and associates this queue with the appropriate consumers. If multiple consumers are connected to the same queue, messages are distributed amongst each consumer equally, providing the consumers are equally able to handle them.

Figure 8.1. Point-to-Point

Publish-Subscribe

Procedure

  1. Open the file BROKER_INSTANCE_DIR/etc/broker.xml for editing.
  2. Wrap an anycast configuration element around the chosen queue element of an address. Ensure the value of address name and queue name elements are same.

    <configuration ...>
      <core ...>
        ...
        <address name="durable">
          <anycast>
            <queue name="durable"/>
          </anycast>
        </address>
      </core>
    </configuration>

8.3. Configuring Publish-Subscribe Messaging

In a publish-subscribe scenario, messages are sent to every consumer subscribed to an address. JMS topics and MQTT subscriptions are two examples of publish-subscribe messaging. When a message is received on an address with a multicast routing type, AMQ Broker routes a copy of the message to each queue. To reduce the overhead of copying, each queue is sent only a reference to the message and not a full copy.

Figure 8.2. Publish-Subscribe

Publish-Subscribe

Procedure

  1. Open the file BROKER_INSTANCE_DIR/etc/broker.xml for editing.
  2. Add an empty multicast configuration element to the chosen address.

    <configuration ...>
      <core ...>
        ...
        <address name="topic.foo">
          <multicast/>
        </address>
      </core>
    </configuration>
  3. (Optional) Add one more queue elements to the address and wrap the multicast element around them. This step is typically not needed since the broker automatically creates a queue for each subscription requested by a client.

    <configuration ...>
      <core ...>
        ...
        <address name="topic.foo">
          <multicast>
            <queue name="client123.topic.foo"/>
            <queue name="client456.topic.foo"/>
          </multicast>
        </address>
      </core>
    </configuration>

8.4. Configuring a Point-to-Point Using Two Queues

You can define more than one queue on an address by using an anycast routing type. Messages semt to an anycast address are distributed evenly across all associated queues. By using Fully Qualified Queue Names, which are described later, you can have clients connect to a specific queue. If more than one consumer connects to the same queue, AMQ Broker distributes messages between them.

Figure 8.3. Point-to-Point with Two Queues

Point-to-Point with Two Queues
Note

This is how AMQ Broker handles load balancing of queues across multiple nodes in a cluster.

Procedure

  1. Open the file BROKER_INSTANCE_DIR/etc/broker.xml for editing.
  2. Wrap an anycast configuration element around the queue elements in the address.

    <configuration ...>
      <core ...>
        ...
        <address name="address.foo">
          <anycast>
            <queue name="q1"/>
            <queue name="q2"/>
          </anycast>
        </address>
      </core>
    </configuration>

8.5. Using Point-to-Point and Publish-Subscribe Together

It is possible to define an address with both point-to-point and publish-subscribe semantics enabled. While not typically recommended, this can be useful when you want, for example, a JMS Queue named orders and a JMS topic named orders. The different routing types make the addresses appear to be distinct.

Using an example of JMS clients, the messages sent by a JMS queue producer are routed using the anycast routing type. Messages sent by a JMS topic producer uses the multicast routing type. In addition, when a JMS topic consumer attaches, it is attached to its own subscription queue. The JMS queue consumer, however, is attached to the anycast queue.

Figure 8.4. Point-to-Point and Publish-Subscribe

Point-to-Point and Publish-Subscribe
Note

The behavior in this scenario is dependent on the protocol being used. For JMS there is a clear distinction between topic and queue producers and consumers, which makes the logic straightforward. Other protocols like AMQP do not make this distinction. A message being sent via AMQP is routed by both anycast and multicast and consumers default to anycast. For more information, check the behavior of each protocol in the sections on protocols.

The XML excerpt below is an example of what the configuration for an address using both anycast and multicast routing types would look like in BROKER_INSTANCE_DIR/etc/broker.xml. Note that subscription queues are typically created on demand, so there is no need to list specific queue elements inside the multicast routing type.

<configuration ...>
  <core ...>
    ...
    <address name="foo.orders">
      <anycast>
        <queue name="orders"/>
      </anycast>
      <multicast/>
    </address>
  </core>
</configuration>

8.6. Configuring Subscription Queues

In most cases it is not necessary to pre-create subscription queues because protocol managers create subscription queues automatically when clients first request to subscribe to an address. See Protocol Managers and Addresses for more information. For durable subscriptions, the generated queue name is usually a concatenation of the client id and the address.

Configuring a Durable Subscription Queue

When an queue is configured as a durable subscription, the broker saves messages for any inactive subscribers and delivers them to the subscribers when they reconnect. Clients are therefore guaranteed to receive each message delivered to the queue after subscribing to it.

Procedure

  1. Open the file BROKER_INSTANCE_DIR/etc/broker.xml for editing.
  2. Add the durable configuration element to the chosen queue and assign it a value of true.

    <configuration ...>
      <core ...>
        ...
        <address name="durable.foo">
          <multicast>
            <queue name="q1">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>

Configuring a Non-Shared Durable Subscription

The broker can be configured to prevent more than one consumer from connecting to a queue at any one time. The subscriptions to queues configured this way are therefore "non-shared".

Procedure

  1. Open the file BROKER_INSTANCE_DIR/etc/broker.xml for editing.
  2. Add the durable configuration element to each chosen queue.

    <configuration ...>
      <core ...>
        ...
        <address name="non.shared.durable.foo">
          <multicast>
            <queue name="orders1">
              <durable>true</durable>
            </queue>
            <queue name="orders2">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>
  3. Add the max-consumers attribute to each chosen queue element and assign it a value of 1.

    <configuration ...>
      <core ...>
        ...
        <address name="non.shared.durable.foo">
          <multicast>
            <queue name="orders1" max-consumers="1">
              <durable>true</durable>
            </queue>
            <queue name="orders2" max-consumers="1">
              <durable>true</durable>
            </queue>
          </multicast>
        </address>
      </core>
    </configuration>

8.7. Using a Fully Qualified Queue Name

Internally the broker maps a client’s request for an address to specific queues. The broker decides on behalf of the client which queues to send messages, or from which queue to receive messages. However, more advanced use cases might require that the client specify a queue directly. In these situations the client can use a Fully Qualified Queue Name (FQQN), by specifying both the address name and the queue name, separated by a ::.

Note

Only message consumers can use FQQN. Do not use FQQN with message producers.

Prerequisites

  • An address is configured with two or more queues. In the example below the address foo has two queues, q1 and q2.

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="foo">
              <anycast>
                 <queue name="q1" />
                 <queue name="q2" />
              </anycast>
           </address>
        </addresses>
      </core>
    </configuration>

Procedure

  • In the client code, use both the address name and the queue name when requesting a connection from the broker. Remember to use two colons, ::, to separate the names, as in the example Java code below.

    String FQQN = "foo::q1";
    Queue q1 session.createQueue(FQQN);
    MessageConsumer consumer = session.createConsumer(q1);

8.8. Configuring Sharded Queues

A common pattern for processing of messages across a queue where only partial ordering is required is to use queue sharding. In AMQ Broker this can be achieved by creating an anycast address that acts as a single logical queue, but which is backed by many underlying physical queues.

Procedure

  1. Open BROKER_INSTANCE_DIR/etc/broker.xml and add an address with the desired name. In the example below the address named sharded is added to the configuration.

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="sharded"></address>
        </addresses>
      </core>
    </configuration>
  2. Add the anycast routing type and include the desired number of sharded queues. In the example below, the queues q1, q2, and q3 are added as anycast destinations.

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="sharded">
              <anycast>
                 <queue name="q1" />
                 <queue name="q2" />
                 <queue name="q3" />
              </anycast>
           </address>
        </addresses>
    </core>
    </configuration>

Using the configuration above, messages sent to sharded are distributed equally across q1, q2 and q3. Clients are able to connect directly to a specific physical queue when using a fully qualified queue name and receive messages sent to that specific queue only.

To tie particular messages to a particular queue, clients can specify a message group for each message. The broker routes grouped messages to the same queue, and one consumer processes them all. See the chapter on Message Grouping for more information.

8.9. Limiting the Number of Consumers Connected to a Queue

You can limit the number of consumers connected to for a particular queue by using the max-consumers attribute. Create an exclusive consumer by setting max-consumers flag can be set to 1. The default value is -1, which is sets an unlimited number of consumers.

Procedure

  1. Open BROKER_INSTANCE_DIR/etc/broker.xml and add the max-consumers attribute to the desired queue. In the example below, only 20 consumers can connect to the queue q3 at the same time.

    <configuration ...>
      <core ...>
        ...
        <addresses>
           <address name="foo">
              <anycast>
                 <queue name="q3" max-consumers="20"/>
              </anycast>
           </address>
        </addresses>
      </core>
    </configuration>
  2. (Optional) Create an exclusive consumer by setting max-consumers to 1, as in the example below.

    <configuration ...>
      <core ...>
        ...
        <address name="foo">
          <anycast>
            <queue name="q3" max-consumers="1"/>
          </anycast>
        </address>
      </core>
    </configuration>
  3. (Optional) Have an unlimited number of consumers by setting max-consumers to -1, as in the example below.

    <configuration ...>
      <core ...>
        ...
        <address name="foo">
          <anycast>
             <queue name="q3" max-consumers="-1"/>
          </anycast>
        </address>
      </core>
    </configuration>

8.10. Configuring a Prefix to Connect to a Specific Routing Type

Normally, if a message is received by an address that uses both anycast and multicast, one of the anycast queues receive the message and all of the multicast queues. However, clients can specify a special prefix when connecting to an address to specify whether to connect using anycast or multicast. The prefixes are custom values that are designated using the anycastPrefix and multicastPrefix parameters within the URL of an acceptor.

Configuring an Anycast Prefix

  • In BROKER_INSTANCE_DIR/etc/broker.xml, add the anycastPrefix to the URL of the desired acceptor. In the example below, the acceptor is configured to use anycast:// for the anycastPrefix. Client code can specify anycast://foo/ if the client needs to send a message to only one of the anycast queues.
<configuration ...>
  <core ...>
    ...
      <acceptors>
         <!-- Acceptor for every supported protocol -->
         <acceptor name="artemis">tcp://0.0.0.0:61616?protocols=AMQP&anycastPrefix=anycast://</acceptor>
      </acceptors>
    ...
  </core>
</configuration>

Configuring a Multicast Prefix

  • In BROKER_INSTANCE_DIR/etc/broker.xml, add the anycastPrefix to the URL of the desired acceptor. In the example below, the acceptor is configured to use multicast:// for the multicastPrefix. Client code can specify multicast://foo/ if the client needs the message sent to only the multicast queues of the address.
<configuration ...>
  <core ...>
    ...
      <acceptors>
         <!-- Acceptor for every supported protocol -->
         <acceptor name="artemis">tcp://0.0.0.0:61616?protocols=AMQP&multicastPrefix=multicast://</acceptor>
      </acceptors>
    ...
  </core>
</configuration>

8.11. Protocol Managers and Addresses

A protocol manager maps protocol-specific concepts down to the AMQ Broker address model concepts: queues and routing types. For example, when a client sends a MQTT subscription packet with the addresses /house/room1/lights and /house/room2/lights, the MQTT protocol manager understands that the two addresses require multicast semantics. The protocol manager therefore first looks to ensure that multicast is enabled for both addresses. If not, it attempts to dynamically create them. If successful, the protocol manager then creates special subscription queues for each subscription requested by the client.

Each protocol behaves slightly differently. The table below describes what typically happens when subscribe frames to various types of queue are requested.

Table 8.2. Protocol Manager Actions

If the queue is of this type…​The typical action for a protocol manager is to…​

Durable Subscription Queue

Look for the appropriate address and ensures that multicast semantics is enabled. It then creates a special subscription queue with the client ID and the address as its name and multicast as its routing type.

The special name allows the protocol manager to quickly identify the required client subscription queues should the client disconnect and reconnect at a later date.

When the client unsubscribes the queue is deleted.

Temporary Subscription Queue

Look for the appropriate address and ensures that multicast semantics is enabled. It then creates a queue with a random (read UUID) name under this address with multicast routing type.

When the client disconnects the queue is deleted.

Point-to-Point Queue

Look for the appropriate address and ensures that anycast routing type is enabled. If it is, it aims to locate a queue with the same name as the address. If it does not exist, it looks for the first queue available. It this does not exist then it automatically creates the queue (providing auto create is enabled). The queue consumer is bound to this queue.

If the queue is auto created, it is automatically deleted once there are no consumers and no messages in it.

8.12. Disabling Advisory Messages

By default, AMQ creates advisory messages about addresses and queues when an OpenWire client is connected to the broker. Advisory messages are sent to internally managed addresses created by the broker. These addresses appear on the AMQ Console within the same display as user-deployed addresses and queues. Although they provide useful information, advisory messages can cause unwanted consequences when the broker manages a large number of destinations. For example, the messages might increase memory usage or strain connection resources. Also, the AMQ Console might become cluttered when attempting to display all of the addresses created to send advisory messages. To avoid these situations, use the supportAdvisory and suppressInternalManagementObjects parameters to manage the advisory messages behavior on the broker side.

  • supportAdvisory: Set this option to true to enable creation of advisory messages or false to disable them. The default value is true.
  • suppressInternalManagementObjects: Set this option to true to expose the advisory messages to the management service such as JMX registry and AMQ Console, or false to not expose them. The default value is true.

Use these parameters by editing the BROKER_INSTANCE_DIR/etc/broker.xml configuration file and configure the parameters on openwire acceptors by using URLs. For example:

<acceptor name="artemis">tcp://127.0.0.1:61616?protocols=CORE,AMQP,OPENWIRE;supportAdvisory=false;suppressInternalManagementObjects=false</acceptor>

8.13. Configuring Address Settings

AMQ Broker has several configurable options that control aspects of how and when a message is delivered, how many attempts should be made, and when the message expires. These configuration options all exist within the <address-setting> configuration element. You can have AMQ Broker apply a single <address-setting> to multiple destinations by using a wildcard syntax.

AMQ Broker Wildcard Syntax

AMQ Broker uses a specific syntax for representing wildcards in security settings, address settings, and when creating consumers.

  • A wildcard expression contains words delimited by the character ‘.’.
  • The special characters ‘#’ and ‘*’ also have special meaning and can take the place of a word.
  • The character ‘#’ means 'match any sequence of zero or more words'. Use this at the end of your expression.
  • The character ‘*’ means 'match a single word'. Use this anywhere within your expression.

Matching is not done character by character, but at each delimiter boundary. For example, an address-setting looking to match queues using my in their name would not match with a queue named myqueue.

When more than one address-setting matches a queue, the broker will overlay configurations, using the configuration of the least specific match as the baseline. Literal expressions are more specific than wildcards, and * is more specific than #. For example, both my.queue and my.* match the queue my.queue. In this case, the broker first applies the configuration found under my.*, since a wildcard expression is less specific than a literal. Next, the broker overlays the configuration of the my.queue address-setting, which will overwrite any configuration shared with my.*. Given the configuration below, the queue my.queue would have max-delivery-attempts set to 3 and last-value-queue set to false.

<address-setting match="my.*">
    <max-delivery-attempts>3</max-delivery-attempts>
    <last-value-queue>true</last-value-queue>
</address-setting>
<address-setting match="my.queue">
    <last-value-queue>false</last-value-queue>
</address-setting>

The examples in the table below illustrate how wildcards are used to match a set of addresses.

Table 8.3. Wildcard Examples

ExampleDescription

#

The default address-setting used in broker.xml. Matches every address. You can continue to apply this catch-all, or you can add a new address-setting for each address or group of addresses as the need arises.

news.europe.#

Matches news.europe, news.europe.sport, news.europe.politics.fr, but not news.usa or europe.

news.*

Matches news.europe and news.usa, but not news.europe.sport.

news.*.sport

Matches news.europe.sport and news.usa.sport, but not news.europe.fr.sport.

Configuring Wildcard Syntax

You can customize the syntax used for wildcard addresses by adding configuration to broker.xml.

Procedure

  • Edit broker.xml by adding a <wildcard-addresses> section to the configuration, as in the example below.
<configuration>
  <core>
    ...
    <wildcard-addresses> 1
      <enabled>true</enabled> 2
      <delimiter>,</delimiter> 3
      <any-words>@</any-words> 4
      <single-word>$</single-word> 5
    </wildcard-addresses>
    ...
  </core>
</configuration>
1
Add wildcard-addresses beneath the core configuration element.
2
Set enabled to true to tell the broker to use your custom settings.
3
Provide a custom character to use as the delimiter instead of the default, which is ..
4
The character provided as the value for any-words is used to mean 'match any sequence of zero or more words' and will replace the default #. Use this character at the end of your expression.
5
The character provided as the value for single-word is used to mean 'match a single word' and will replaced the default *. Use this character anywhere within your expression.

8.14. Creating and Deleting Queues and Addresses Automatically

You can configure AMQ Broker to automatically create addresses and queues, and to delete them after they are no longer in use. This saves you from having to pre-configure each address before a client can connect to it.

Automatic creation and deletion of queues and addresses is configured on a per address-setting basis. The configuration is applied to any address or queue that is a match for the address-setting. See Configuring Address Settings for more information about how to use wildcard syntax to match addresses and queues to an address-setting.

The table below lists the configuration elements available when configuring an address-setting to automatically create and delete its queues and addresses.

If you want the address-setting to…​Add this configuration…​

Create addresses when a client sends a message to or attempts to consume a message from a queue mapped to an address that doesn’t exist.

auto-create-addresses

Create a queue when a client sends a message to or attempts to consume a message from a queue.

auto-create-queues

Delete an automatically-created address when it no longer has any queues.

auto-delete-addresses

Delete an automatically-created queue when the queue has 0 consumers and 0 messages.

auto-delete-queues

Use a specific routing type if the client does not specify one.

default-address-routing-type

Procedure

Edit the file BROKER_INSTANCE_DIR/etc/broker.xml and configure an address-setting for automatic creation and deletion. The example below uses all of the configuration elements mentioned in the table above.

<configuration ...>
 <core ...>
  ...
  <address-settings>
    <address-setting match="/news/politics/#"> 1
      <auto-create-addresses>true</auto-create-addresses> 2
      <auto-delete-addresses>true</auto-delete-addresses> 3
      <auto-create-queues>true</auto-create-queues> 4
      <auto-delete-queues>true</auto-delete-queues> 5
      <default-address-routing-type>ANYCAST</default-address-routing-type> 6
    </address-setting>
  </address-settings>
  ...
 </core>
</configuration>
1
The configuration included in this address-setting is applied to any address or queue that matches the wildcard /news/politics/#. For more information on using wildcard syntax see AMQ Broker Widcard Syntax.
2
The broker creates an address that does not exist when a client requests it.
3
An automatically-created address is deleted when it no longer has any queues associated with it.
4
The broker creates a queue that does not exist when a client requests it.
5
An automatically-created queue is deleted when it no longer has any consumers or messages.
6
If the client does not specify a routing type when connecting, the broker uses ANYCAST when delivering messages to an address. The default value is MULTICAST. See the introduction of this chapter for more information about routing types.