blob: 5a21834ffe53b6b444696514276a2da6cc0006a8 [file] [log] [blame]
////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License
////
[id='routing']
= Routing messages through the router network
Routing is the process by which messages are delivered to their destinations. To accomplish this, {RouterName} provides two routing mechanisms: _message routing_ and _link routing_.
Message routing:: Routing is performed on messages as producers send them to a router. When a message arrives on a router, the router routes the message and its _settlement_ based on the message's _address_ and _routing pattern_.
+
--
.Message Routing
image::message-routing.png[Message Routing, align="center"]
In this diagram, the message producer attaches a link to the router, and then sends a message over the link. When the router receives the message, it identifies the message's destination based on the message's address, and then uses its routing table to determine the best route to deliver the message either to its destination or to the next hop in the route. All dispositions (including settlement) are propagated along the same path that the original message transfer took. Flow control is handled between the sender and the router, and then between the router and the receiver.
--
Link routing:: Routing is performed on link-attach frames, which are chained together to form a virtual messaging path that directly connects a sender and receiver. Once a link route is established, the transfer of message deliveries, flow frames, and dispositions is performed across the link route.
+
--
.Link Routing
image::link-routing.png[Link Routing, align="center"]
In this diagram, a router is connected to clients and to a broker, and it provides a link route to a queue on the broker (my_queue). The sender connects to the router, and the router propagates the link-attaches to the broker to form a direct link between the sender and the broker. The sender can begin sending messages to the queue, and the router passes the deliveries along the link route directly to the broker queue.
--
== Comparison of Message Routing and Link Routing
While you can use either message routing or link routing to deliver messages to a destination, they differ in several important ways. Understanding these differences will enable you to choose the proper routing approach for any particular use case.
=== When to Use Message Routing
Message routing is the default routing mechanism. You can use it to route messages on a per-message basis between clients directly (direct-routed messaging), or to and from broker queues (brokered messaging).
Message routing is best suited to the following requirements:
* Default, basic message routing.
+
{RouterName} automatically routes messages by default, so manual configuration is only required if you want routing behavior that is different than the default.
* Message-based routing patterns.
+
Message routing supports both anycast and multicast routing patterns. You can load-balance individual messages across multiple consumers, and multicast (or fan-out) messages to multiple subscribers.
* Sharding messages across multiple broker instances when message delivery order is not important.
+
Sharding messages from one producer might cause that producer's messages to be received in a different order than the order in which they were sent.
Message routing is not suitable for any of the following requirements:
* Dedicated path through the router network.
+
For inter-router transfers, all message deliveries are placed on the same inter-router link. This means that the traffic for one address might affect the delivery of the traffic for another address.
* Granular, end-to-end flow control.
+
With message routing, end-to-end flow control is based on the settlement of deliveries and therefore might not be optimal in every case.
* Transaction support.
* Server-side selectors.
=== When to Use Link Routing
Link routing requires more detailed configuration than message routing as well as an AMQP container that can accept incoming link-attaches (typically a broker). However, link routing enables you to satisfy more advanced use cases than message routing.
You can use link routing if you need to meet any of the following requirements:
* Dedicated path through the router network.
+
With link routing, each link route has dedicated inter-router links through the network. Each link has its own dedicated message buffers, which means that the address will not have "head-of-line" blocking issues with other addresses.
* Sharding messages across multiple broker instances with guaranteed delivery order.
+
Link routing to a sharded queue preserves the delivery order of the producer's messages by causing all messages on that link to go to the same broker instance.
* End-to-end flow control.
+
Flow control is "real" in that credits flow across the link route from the receiver to the sender.
* Transaction support.
+
Link routing supports local transactions to a single broker. Distributed transactions are not supported.
* Server-side selectors.
+
With a link route, consumers can provide server-side selectors for broker subscriptions.
[id='configuring-message-routing']
== Configuring Message Routing
With message routing, routing is performed on messages as producers send them to a router. When a message arrives on a router, the router routes the message and its _settlement_ based on the message's _address_ and _routing pattern_.
With message routing, you can do the following:
* Route messages between clients (direct-routed, or brokerless messaging)
+
This involves configuring an address with a routing pattern. All messages sent to the address will be routed based on the routing pattern.
* Route messages through a broker queue (brokered messaging)
+
This involves configuring a waypoint address to identify the broker queue and then connecting the router to the broker. All messages sent to the waypoint address will be routed to the broker queue.
=== Message Routing Flow Control
{RouterName} uses a _credit-based_ flow control mechanism to ensure that producers can only send messages to a router if at least one consumer is available to receive them. Because {RouterName} does not store messages, this credit-based flow control prevents producers from sending messages when there are no consumers present.
A client wishing to send a message to the router must wait until the router has provided it with credit. Attempting to publish a message without credit available will cause the client to block. Once credit is made available, the client will unblock, and the message will be sent to the router.
NOTE: Most AMQP client libraries enable you to determine the amount of credit available to a producer. For more information, consult your client's documentation.
=== Addresses
Addresses determine how messages flow through your router network. An address designates an endpoint in your messaging network, such as:
* Endpoint processes that consume data or offer a service
* Topics that match multiple consumers to multiple producers
* Entities within a messaging broker:
** Queues
** Durable Topics
** Exchanges
When a router receives a message, it uses the message's address to determine where to send the message (either its destination or one step closer to its destination).
==== Mobile Addresses
Routers consider addresses to be mobile such that any users of an
address may be directly connected to any router in a network and may
move around the topology. In cases where messages are broadcast to or
balanced across multiple consumers, the address users may be connected
to multiple routers in the network.
Mobile addresses are rendezvous points for senders and receivers.
Messages arrive at the mobile address and are dispatched to their
destinations according to the routing defined for the mobile address.
The details of these routing patterns are discussed later.
Mobile addresses may be discovered during normal router operation or
configured through management settings.
===== Discovered Mobile Addresses
Mobile addresses are created when a client creates a link to a source
or destination address that is unknown to the router network.
Suppose a service provider wants to offer _my-service_ that clients
may use. The service provider must open a receiver link with source
address _my-service_. The router creates a mobile address
_my-service_ and propagates the address so that it is known to every
router in the network.
Later a client wants to use the service and creates a sending link
with target address _my-service_. The router matches the service
provider's receiver having source address _my-service_ to the client's
sender having target address _my-service_ and routes messages between
the two.
Any number of other clients can create links to the service as
well. The clients do not have to know where in the router network the
service provider is physically located nor are the clients required to
connect to a specific router to use the service. Regardless of how
many clients are using the service the service provider needs only a
single connection and link into the router network.
Another view of this same scenario is when a client tries to use the
service before service provider has connected to the network. In this
case the router network creates the mobile address _my-service_ as
before. However, since the mobile address has only client sender links
and no receiver links the router stalls the clients and prevents them
from sending any messages. Later, after the service provider connects
and creates the receiver link, the router will issue credits to the
clients and the messages will begin to flow between the clients and
the service.
The service provider can connect, disconnect, and reconnect from a
different location without having to change any of the clients or
their connections. Imagine having the service running on a
laptop. One day the connection is from corporate headquarters and the
next day the connection is from some remote location. In this case the
service provider's computer will typically have different host IP
addresses for each connection. Using the router network the service
provider connects to the router network and offers the named service
and the clients connect to the router network and consume from the
named service. The router network routes messages between the mobile
addresses effectively masking host IP addresses of the service
provider and the client systems.
===== Configured Mobile Addresses
Mobile addresses may be configured using the router _autoLink_
object. An address created via an _autoLink_ represents a queue,
topic, or other service in an external broker. Logically the
_autoLink_ addresses are treated by the router network as if the
broker had connected to the router and offered the services itself.
For each configured mobile address the router will create a single
link to the external resource. Messages flow between sender links and
receiver links the same regardless if the mobile address was
discovered or configured.
Multiple _autoLink_ objects may define the same address on multiple
brokers. In this case the router network creates a sharded resource
split between the brokers. Any client can seamlessly send and receive
messages from either broker.
Note that the brokers do not need to be clustered or federated to
receive this treatment. The brokers may even be from different vendors
or be different versions of the same broker yet still work together to
provide a larger service platform.
[id='routing-patterns-overview']
=== Routing Patterns
Routing patterns define the paths that a message with a mobile address
can take across a network. These routing patterns can be used for both
direct routing, in which the router distributes messages between
clients without a broker, and indirect routing, in which the router
enables clients to exchange messages through a broker.
Routing patterns fall into two categories: Anycast
(Balanced and Closest) and Multicast. There is no concept of
"unicast" in which there is only one consumer for an address.
Anycast distribution delivers each message to one consumer whereas
multicast distribution delivers each message to all consumers.
Each address has one of the following routing patterns, which define the path that a message with the address can take across the messaging network:
Balanced:: An anycast method that allows multiple consumers to use the same address. Each message is delivered to a single consumer only, and {RouterName} attempts to balance the traffic load across the router network.
+
--
If multiple consumers are attached to the same address, each router determines which outbound path should receive a message by considering each path's current number of unsettled deliveries. This means that more messages will be delivered along paths where deliveries are settled at higher rates.
[NOTE]
====
{RouterName} neither measures nor uses message settlement time to determine which outbound path to use.
====
In this scenario, the messages are spread across both receivers regardless of path length:
.Balanced Message Routing
image::balanced-routing.png[Balanced Message Routing, align="center"]
--
Closest:: An anycast method in which every message is sent along the shortest path to reach the destination, even if there are other consumers for the same address.
+
{RouterName} determines the shortest path based on the topology cost to reach each of the consumers. If there are multiple consumers with the same lowest cost, messages will be spread evenly among those consumers.
+
In this scenario, all messages sent by `Sender` will be delivered to `Receiver 1`:
+
.Closest Message Routing
image::closest-routing.png[Closest Message Routing, align="center"]
Multicast:: Messages are sent to all consumers attached to the address. Each consumer will receive one copy of the message.
+
In this scenario, all messages are sent to all receivers:
+
.Multicast Message Routing
image::multicast-routing.png[Multicast Message Routing, align="center"]
=== Message Settlement and Reliability
{RouterName} can deliver messages with the following degrees of reliability:
* At most once
* At least once
* Exactly once
The level of reliability is negotiated between the producer and the router when the producer establishes a link to the router. To achieve the negotiated level of reliability, {RouterName} treats all messages as either _pre-settled_ or _unsettled_.
Pre-settled::
Sometimes called _fire and forget_, the router settles the incoming and outgoing deliveries and propagates the settlement to the message's destination. However, it does not guarantee delivery.
Unsettled::
{RouterName} propagates the settlement between the producer and consumer. For an anycast address, the router associates the incoming delivery with the resulting outgoing delivery. Based on this association, the router propagates changes in delivery state from the consumer to the producer.
+
For a multicast address, the router associates the incoming delivery with all outbound deliveries. The router waits for each consumer to set their delivery's final state. After all outgoing deliveries have reached their final state, the router sets a final delivery state for the original inbound delivery and passes it to the producer.
+
The following table describes the reliability guarantees for unsettled messages sent to an anycast or multicast address:
+
[cols="20,40,40"]
|===
| Final disposition | Anycast | Multicast
| `accepted`
| The consumer received the message.
a|
Either:
* All consumers received the message,
* Or, at least one consumer received the message, but no consumers rejected it.
| `released`
| The message did not reach its destination.
| The message did not reach any of the consumers.
| `modified`
| The message may or may not have reached its destination. The delivery is considered to be "in-doubt" and should be re-sent if "at least once" delivery is required.
| The message may or may not have reached any of the consumers. However, no consumers rejected or accepted it.
| `rejected`
| The consumer rejected the message.
| At least one consumer rejected the message.
|===
[id='prioritized-message-delivery']
=== Configuring Addresses for Prioritized Message Delivery
You can set the priority level of an address to control how {RouterName} processes messages sent to that address. Within the scope of a connection, {RouterName} attempts to process messages based on their priority. For a connection with a large volume of messages in flight, this lowers the latency for higher-priority messages.
Assigning a high priority level to an address does not guarantee that messages sent to the address will be delivered before messages sent to lower-priority addresses. However, higher-priority messages will travel more quickly through the router network than they otherwise would.
[NOTE]
====
You can also control the priority level of individual messages by setting the priority level in the message header. However, the address priority takes precedence: if you send a prioritized message to an address with a different priority level, the router will use the address priority level.
====
.Procedure
* In the router's configuration file, add or edit an address and assign a priority level.
+
--
This example adds an address with the highest priority level. The router will attempt to deliver messages sent to this address before messages with lower priority levels.
[options="nowrap",subs="+quotes"]
----
address {
prefix: my-high-priority-address
priority: 9
...
}
----
`priority`:: The priority level to assign to all messages sent to this address. The range of valid priority levels is 0-9, in which the higher the number, the higher the priority. The default is 4.
--
.Additional resources
* For more information about setting the priority level in a message, see the {AmqpSpecLink}.
[id='routing-messages-between-clients']
=== Routing Messages Between Clients
You can route messages between clients without using a broker. In a brokerless scenario (sometimes called _direct-routed messaging_), {RouterName} routes messages between clients directly.
To route messages between clients, you configure an address with a routing distribution pattern. When a router receives a message with this address, the message is routed to its destination or destinations based on the address's routing distribution pattern.
.Procedure
. In the router's configuration file, add an `address` section:
+
--
[options="nowrap",subs="+quotes"]
----
address {
prefix: _ADDRESS_PREFIX_
distribution: balanced|closest|multicast
...
}
----
`prefix` | `pattern`:: The address or group of addresses to which the address settings should be applied. You can specify a prefix to match an exact address or beginning segment of an address. Alternatively, you can specify a pattern to match an address using wildcards.
+
//tag::prefix-matching[]
A _prefix_ matches either an exact address or the beginning segment within an address that is delimited by either a `.` or `/` character. For example, the prefix `my_address` would match the address `my_address` as well as `my_address.1` and `my_address/1`. However, it would not match `my_address1`.
//end::prefix-matching[]
+
//tag::pattern-matching[]
A _pattern_ matches an address that corresponds to a pattern. A pattern is a sequence of words delimited by either a `.` or `/` character. You can use wildcard characters to represent a word. The `*` character matches exactly one word, and the `#` character matches any sequence of zero or more words.
+
The `*` and `#` characters are reserved as wildcards. Therefore, you should not use them in the message address.
+
For more information about creating address patterns, see xref:router-address-pattern-matching[].
+
[NOTE]
====
You can convert a `prefix` value to a `pattern` by appending `/\#` to it. For example, the prefix `a/b/c` is equivalent to the pattern `a/b/c/#`.
====
//end::pattern-matching[]
`distribution`:: The message distribution pattern. The default is `balanced`, but you can specify any of the following options:
+
* `balanced` - Messages sent to the address will be routed to one of the receivers, and the routing network will attempt to balance the traffic load based on the rate of settlement.
* `closest` - Messages sent to the address are sent on the shortest path to reach the destination. It means that if there are multiple receivers for the same address, only the closest one will receive the message.
* `multicast` - Messages are sent to all receivers that are attached to the address in a _publish/subscribe_ model.
+
For more information about message distribution patterns, see xref:routing-patterns-overview[Routing Patterns].
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_address[address] in the `qdrouterd.conf` man page.
--
. Add the same `address` section to any other routers that need to use the address.
+
The `address` that you added to this router configuration file only controls how this router distributes messages sent to the address. If you have additional routers in your router network that should distribute messages for this address, then you must add the same `address` section to each of their configuration files.
[id='routing-messages-through-broker']
=== Routing Messages Through a Broker Queue
You can route messages to and from a broker queue to provide clients with access to the queue through a router. In this scenario, clients connect to a router to send and receive messages, and the router routes the messages to or from the broker queue.
You can route messages to a queue hosted on a single broker, or route messages to a _sharded queue_ distributed across multiple brokers.
.Brokered Messaging
image::brokered-messaging.png[Brokered Messaging, align="center"]
In this diagram, the sender connects to the router and sends messages to my_queue. The router attaches an outgoing link to the broker, and then sends the messages to my_queue. Later, the receiver connects to the router and requests messages from my_queue. The router attaches an incoming link to the broker to receive the messages from my_queue, and then delivers them to the receiver.
You can also route messages to a _sharded queue_, which is a single, logical queue comprised of multiple, underlying physical queues. Using queue sharding, it is possible to distribute a single queue over multiple brokers. Clients can connect to any of the brokers that hold a shard to send and receive messages.
.Brokered Messaging with Sharded Queue
image::sharded-queue-02.png[Brokered Messaging with Sharded Queue, align="center"]
In this diagram, a sharded queue (my_queue) is distributed across two brokers. The router is connected to the clients and to both brokers. The sender connects to the router and sends messages to my_queue. The router attaches an outgoing link to each broker, and then sends messages to each shard (by default, the routing distribution is `balanced`). Later, the receiver connects to the router and requests all of the messages from my_queue. The router attaches an incoming link to one of the brokers to receive the messages from my_queue, and then delivers them to the receiver.
.Procedure
. xref:configure-waypoint-address[Add a waypoint address].
+
This address identifies the queue to which you want to route messages.
. xref:connect-router-to-broker[Add autolinks to connect the router to the broker].
+
Autolinks connect the router to the broker queue identified by the waypoint address.
. xref:connect-router-to-broker[If the queue is sharded, add autolinks for each additional broker that hosts a shard].
[id='configure-waypoint-address']
==== Configuring Waypoint Addresses
A waypoint address identifies a queue on a broker to which you want to route messages. You need to configure the waypoint address on each router that needs to use the address. For example, if a client is connected to _Router A_ to send messages to the broker queue, and another client is connected to _Router B_ to receive those messages, then you would need to configure the waypoint address on both _Router A_ and _Router B_.
.Prerequisites
An incoming connection (`listener`) to which the clients can connect should be configured. This connection defines how the producers and consumers connect to the router to send and receive messages. For more information, see xref:listening-client-connections-{context}[].
// Does the broker queue have to exist before you create the waypoint address? If it doesn't exist, will you get an error?
.Procedure
* Create waypoint addresses on each router that needs to use the address:
+
--
[options="nowrap",subs="+quotes"]
----
address {
prefix: _ADDRESS_PREFIX_
waypoint: yes
}
----
`prefix` | `pattern`:: The address prefix or pattern that matches the broker queue to which you want to send messages. You can specify a prefix to match an exact address or beginning segment of an address. Alternatively, you can specify a pattern to match an address using wildcards.
+
include::routing.adoc[tags=prefix-matching]
+
include::routing.adoc[tags=pattern-matching]
`waypoint`:: Set this attribute to `yes` so that the router handles messages sent to this address as a waypoint.
--
[id='connect-router-to-broker']
==== Connecting a Router to the Broker
After you add waypoint addresses to identify the broker queue, you must connect a router to the broker using autolinks.
With autolinks, client traffic is handled on the router, not the broker. Clients attach their links to the router, and then the router uses internal autolinks to connect to the queue on the broker. Therefore, the queue will always have a single producer and a single consumer regardless of how many clients are attached to the router.
[NOTE]
====
If the connection to the broker fails, {RouterName} automatically attempts to reestablish the connection and reroute message deliveries to any available alternate destinations. However, some deliveries could be returned to the sender with a `RELEASED` or `MODIFIED` disposition. Therefore, you should ensure that your clients can handle these deliveries appropriately (generally by resending them).
====
. If this router is different than the router that is connected to the clients, then add the waypoint address.
. Add an outgoing connection to the broker:
+
--
[options="nowrap",subs="+quotes"]
----
connector {
name: _NAME_
host: _HOST_NAME/ADDRESS_
port: _PORT_NUMBER/NAME_
role: route-container
...
}
----
`name`:: The name of the `connector`. Specify a name that describes the broker.
`host`:: Either an IP address (IPv4 or IPv6) or hostname on which the router should connect to the broker.
`port`:: The port number or symbolic service name on which the router should connect to the broker.
`role`:: Specify `route-container` to indicate that this connection is for an external container (broker).
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_connector[connector] in the `qdrouterd.conf` man page.
--
. If you want to send messages to the broker queue, create an outgoing autolink to the broker queue:
+
--
[options="nowrap",subs="+quotes"]
----
autoLink {
address: _ADDRESS_
connection: _CONNECTOR_NAME_
direction: out
...
}
----
`address`:: The address of the broker queue. When the autolink is created, it will be attached to this address.
`externalAddress`:: An optional alternate address for the broker queue. You use an external address if the broker queue should have a different address than that which the sender uses. In this scenario, senders send messages to the `addr` address, and then the router routes them to the broker queue represented by the `externalAddress` address.
`connection` | `containerID`:: How the router should connect to the broker. You can specify either an outgoing connection (`connection`) or the container ID of the broker (`containerID`).
`direction`:: Set this attribute to `out` to specify that this autolink can send messages from the router to the broker.
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_autolink[autoLink] in the `qdrouterd.conf` man page.
--
. If you want to receive messages from the broker queue, create an incoming autolink from the broker queue:
+
--
[options="nowrap",subs="+quotes"]
----
autoLink {
address: _ADDRESS_
connection: _CONNECTOR_NAME_
direction: in
...
}
----
`address`:: The address of the broker queue. When the autolink is created, it will be attached to this address.
`externalAddress`:: An optional alternate address for the broker queue. You use an external address if the broker queue should have a different address than that which the receiver uses. In this scenario, receivers receive messages from the `addr` address, and the router retrieves them from the broker queue represented by the `externalAddress` address.
`connection` | `containerID`:: How the router should connect to the broker. You can specify either an outgoing connection (`connection`) or the container ID of the broker (`containerID`).
`direction`:: Set this attribute to `in` to specify that this autolink can receive messages from the broker to the router.
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_autolink[autoLink] in the `qdrouterd.conf` man page.
--
=== Handling Undeliverable Messages for an Address
You handle undeliverable messages for an address by configuring autolinks that point to _fallback destinations_.
A fallback destination (such as a queue on a broker) stores messages that are not directly routable to any consumers.
During normal message delivery,
{RouterName} delivers messages to the consumers that are attached to the router network.
However, if no consumers are reachable,
the messages are diverted to any fallback destinations that were configured for the address (if the autolinks that point to the fallback destinations are active).
When a consumer reconnects and becomes reachable again,
it receives the messages stored at the fallback destination.
[NOTE]
====
{RouterName} preserves the original delivery order for messages stored at a fallback destination. However, when a consumer reconnects, any new messages produced while the queue is draining will be interleaved with the messages stored at the fallback destination.
====
.Prerequisites
* The router is connected to a broker.
+
For more information, see xref:connecting-to-external-amqp-containers-{context}[].
.Procedure
This procedure enables fallback for an address
and configures autolinks to connect to the broker queue
that provides the fallback destination for the address.
. Enable fallback destinations for the address.
+
[options="nowrap",subs="+quotes"]
----
address {
prefix: my-address
enableFallback: yes
}
----
. Add an _outgoing_ autolink to a queue on the broker.
+
--
For the address for which you enabled fallback,
if messages are not routable to any consumers,
the router will use this autolink to send the messages to a queue on the broker.
[options="nowrap",subs="+quotes"]
----
autoLink {
address: my-address.2
direction: out
connection: my-broker
fallback: yes
}
----
--
. If you want the router to send queued messages to attached consumers as soon as they connect to the router network,
add an _incoming_ autolink.
+
--
As soon as a consumer attaches to the router,
it will receive the messages stored in the broker queue,
along with any new messages sent by the producer.
The original delivery order of the queued messages is preserved;
however, the queued messages will be interleaved with the new messages.
If you do not add the incoming autolink,
the messages will be stored on the broker,
but will not be sent to consumers when they attach to the router.
[options="nowrap",subs="+quotes"]
----
autoLink {
address: my-address.2
direction: in
connection: my-broker
fallback: yes
}
----
--
=== Example: Routing Messages Through Broker Queues
This example shows how waypoints and autolinks can route messages through a pair of queues on a broker.
==== Router Configuration
[options="nowrap"]
----
connector { // <1>
name: broker
role: route-container
host: 198.51.100.1
port: 61617
saslMechanisms: ANONYMOUS
}
address { // <2>
prefix: queue
waypoint: yes
}
autoLink { // <3>
address: queue.first
direction: in
connection: broker
}
autoLink { // <4>
address: queue.first
direction: out
connection: broker
}
autoLink { // <5>
address: queue.second
direction: in
connection: broker
}
autoLink { // <6>
address: queue.second
direction: out
connection: broker
}
----
<1> The outgoing connection from the router to the broker. The `route-container` role enables the router to connect to an external AMQP container (in this case, a broker).
<2> The namespace queue on the broker to which the router should route messages. All addresses that start with `queue` will be routed to a queue on the broker.
<3> The incoming autolink from `queue.first` on the broker to the router.
<4> The outgoing autolink from the router to `queue.first` on the broker.
<5> The incoming autolink from `queue.second` on the broker to the router.
<6> The outgoing autolink from the router to `queue.second` on the broker.
==== How the Messages are Routed
Initially, when the broker is offline, the autolinks are inactive.
[options="nowrap"]
----
$ qdstat --autolinks
AutoLinks
addr dir phs extAddr link status lastErr
========================================================
queue.first in 1 inactive
queue.first out 0 inactive
queue.second in 1 inactive
queue.second out 0 inactive
----
Once the broker is online, the autolinks attempt to activate. In this case, the broker starts with the `queue.first` queue only, and the `queue.first` autolinks become active. The `queue.second` autolinks are in a failed state, because the `queue.second` queue does not exist on the broker.
[options="nowrap"]
----
$ qdstat --autolinks
AutoLinks
addr dir phs extAddr link status lastErr
===========================================================================
queue.first in 1 6 active
queue.first out 0 7 active
queue.second in 1 failed Node not found: queue.second
queue.second out 0 failed Node not found: queue.second
----
The producer now connects to the router and sends three messages to `queue.first`.
[options="nowrap"]
----
$ python simple_send.py -a 127.0.0.1/queue.first -m3
all messages confirmed
----
The router's address statistics show that the messages were delivered to the queue.
[options="nowrap"]
----
$ qdstat -a
Router Addresses
class addr phs distrib in-proc local remote cntnr in out thru to-proc from-proc
========================================================================================================
mobile queue.first 1 balanced 0 0 0 0 0 0 0 0 0
mobile queue.first 0 balanced 0 1 0 0 3 3 0 0 0
----
The `queue.first` address appears twice in the output: once for each phase of the address. Phase 0 is for routing messages from producers to the outgoing autolink. Phase 1 is for routing messages from the incoming autolink to the subscribed consumers. In this case, Phase 0 of the address has counted three messages in the `in` column (the messages that arrived on the router from the producer), and three messages in the `out` column (the messages that were sent from the router to the broker queue).
The consumer now connects to the router and receives the three messages from `queue.first`.
[options="nowrap"]
----
$ python simple_recv.py -a 127.0.0.1:5672/queue.first -m3
{u'sequence': int32(1)}
{u'sequence': int32(2)}
{u'sequence': int32(3)}
----
The router's address statistics now show that all three messages were received by the consumer from the broker queue.
[options="nowrap"]
----
$ qdstat -a
Router Addresses
class addr phs distrib in-proc local remote cntnr in out thru to-proc from-proc
========================================================================================================
mobile queue.first 1 balanced 0 0 0 0 3 3 0 0 0
mobile queue.first 0 balanced 0 1 0 0 3 3 0 0 0
----
The command output shows that Phase 1 of the address was used to deliver all three messages from the queue to the consumer.
[NOTE]
====
Even in a multi-router network, and with multiple producers and consumers for `queue.first`, all deliveries are routed through the queue on the connected broker.
====
[id='configuring-link-routing']
== Configuring Link Routing
Link routing provides an alternative strategy for brokered messaging. A link route represents a private messaging path between a sender and a receiver in which the router passes the messages between end points. You can think of a link route as a "virtual connection" or "tunnel" that travels from a sender, through the router network, to a receiver.
With link routing, routing is performed on link-attach frames, which are chained together to form a virtual messaging path that directly connects a sender and receiver. Once a link route is established, the transfer of message deliveries, flow frames, and dispositions is performed across the link route.
=== Link Route Addresses
A link route address represents a broker queue, topic, or other service. When a client attaches a link route address to a router, the router propagates a link attachment to the broker resource identified by the address.
Using link route addresses, the router network does not participate in
aggregated message distribution. The router simply passes message
delivery and settlement between the two end points.
=== Link Route Routing Patterns
Routing patterns are not used with link routing, because there is a direct link between the sender and receiver. The router only makes a routing decision when it receives the initial link-attach request frame. Once the link is established, the router passes the messages along the link in a balanced distribution.
=== Link Route Flow Control
Unlike message routing, with link routing, the sender and receiver handle flow control directly: the receiver grants link credits, which is the number of messages it is able to receive. The router sends them directly to the sender, and then the sender sends the messages based on the credits that the receiver granted.
// What additional information do we need to provide about AMQP link flow control options? Since this is handled on the client side for link routing, should we provide a simple example with a client program that implements link flow control?
[id='creating-link-route']
=== Creating a Link Route
Link routes establish a link between a sender and a receiver that travels through a router. You can configure inward and outward link routes to enable the router to receive link-attaches from clients and to send them to a particular destination.
With link routing, client traffic is handled on the broker, not the router. Clients have a direct link through the router to a broker's queue. Therefore, each client is a separate producer or consumer.
[NOTE]
====
If the connection to the broker fails, the routed links are detached, and the router will attempt to reconnect to the broker (or its backup). Once the connection is reestablished, the link route to the broker will become reachable again.
From the client's perspective, the client will see the detached links (that is, the senders or receivers), but not the failed connection. Therefore, if you want the client to reattach dropped links in the event of a broker connection failure, you must configure this functionality on the client. Alternatively, you can use message routing with autolinks instead of link routing. For more information, see xref:routing-messages-through-broker[Routing Messages through a Broker Queue].
====
.Procedure
. In the router configuration file, add an outgoing connection to the broker:
+
--
[options="nowrap",subs="+quotes"]
----
connector {
name: _NAME_
host: _HOST_NAME/ADDRESS_
port: _PORT_NUMBER/NAME_
role: route-container
...
}
----
`name`:: The name of the `connector`. You should specify a name that describes the broker.
`host`:: Either an IP address (IPv4 or IPv6) or hostname on which the router should connect to the broker.
`port`:: The port number or symbolic service name on which the router should connect to the broker.
`role`:: Specify `route-container` to indicate that this connection is for an external container (broker).
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_connector[connector] in the `qdrouterd.conf` man page.
--
. If you want clients to send local transactions to the broker, create a link route for the transaction coordinator:
+
--
[options="nowrap",subs="+quotes"]
----
linkRoute {
prefix: $coordinator <1>
connection: __CONNECTOR_NAME__
direction: in
}
----
<1> The `$coordinator` prefix designates this link route as a transaction coordinator. When the client opens a transacted session, the requests to start and end the transaction are propagated along this link route to the broker.
{RouterName} does not support routing transactions to multiple brokers. If you have multiple brokers in your environment, choose a single broker and route all transactions to it.
--
. If you want clients to send messages on this link route, create an incoming link route:
+
--
[options="nowrap",subs="+quotes"]
----
linkRoute {
prefix: __ADDRESS_PREFIX__
connection: __CONNECTOR_NAME__
direction: in
...
}
----
`prefix` | `pattern`:: The address prefix or pattern that matches the broker queue that should be the destination for routed link-attaches. All messages that match this prefix or pattern will be distributed along the link route. You can specify a prefix to match an exact address or beginning segment of an address. Alternatively, you can specify a pattern to match an address using wildcards.
+
include::routing.adoc[tags=prefix-matching]
+
include::routing.adoc[tags=pattern-matching]
`connection` | `containerID`:: How the router should connect to the broker. You can specify either an outgoing connection (`connection`) or the container ID of the broker (`containerID`).
+
If multiple brokers are connected to the router through this connection, requests for addresses matching the link route's prefix or pattern are balanced across the brokers. Alternatively, if you want to specify a particular broker, use `containerID` and add the broker's container ID.
`direction`:: Set this attribute to `in` to specify that clients can send messages into the router network on this link route.
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_linkroute[linkRoute] in the `qdrouterd.conf` man page.
--
. If you want clients to receive messages on this link route, create an outgoing link route:
+
--
[options="nowrap",subs="+quotes"]
----
linkRoute {
prefix: __ADDRESS_PREFIX__
connection: __CONNECTOR_NAME__
direction: out
...
}
----
`prefix` | `pattern`:: The address prefix or pattern that matches the broker queue from which you want to receive routed link-attaches. All messages that match this prefix or pattern will be distributed along the link route. You can specify a prefix to match an exact address or beginning segment of an address. Alternatively, you can specify a pattern to match an address using wildcards.
+
include::routing.adoc[tags=prefix-matching]
+
include::routing.adoc[tags=pattern-matching]
`connection` | `containerID`:: How the router should connect to the broker. You can specify either an outgoing connection (`connection`) or the container ID of the broker (`containerID`).
+
If multiple brokers are connected to the router through this connection, requests for addresses matching the link route's prefix or pattern are balanced across the brokers. Alternatively, if you want to specify a particular broker, use `containerID` and add the broker's container ID.
`direction`:: Set this attribute to `out` to specify that this link route is for receivers.
For information about additional attributes, see link:{qdrouterdConfManPageUrl}#_linkroute[linkRoute] in the `qdrouterd.conf` man page.
--
=== Example: Using a Link Route to Provide Client Isolation
This example shows how a link route can connect a client to a message broker that is on a different private network.
.Router Network with Isolated Clients
----
Public Network
+-----------------+
| +-----+ |
| B1 | Rp | |
| +/--\-+ |
| / \ |
| / \ |
+----/--------\---+
/ \
/ \
/ \
Private Net A / \ Private Net B
+--------------/--+ +---\-------------+
| +---/-+ | | +--\--+ |
| B2 | Ra | | | | Rb | C1 |
| +-----+ | | +-----+ |
| | | |
| | | |
+-----------------+ +-----------------+
----
Client `C1` is constrained by firewall policy to connect to the router in its own network (`Rb`). However, it can use a link route to access queues, topics, and any other AMQP services that are provided on message brokers `B1` and `B2` -- even though they are on different networks.
In this example, client `C1` needs to receive messages from `b2.event-queue`, which is hosted on broker `B2` in `Private Net A`. A link route connects the client and broker even though neither of them is aware that there is a router network between them.
==== Router Configuration
To enable client `C1` to receive messages from `b2.event-queue` on broker `B2`, router `Ra` must be able to do the following:
* Connect to broker `B2`
* Route links to and from broker `B2`
* Advertise itself to the router network as a valid destination for links that have a `b2.event-queue` address.
The relevant part of the configuration file for router `Ra` shows the following:
--
[options="nowrap"]
----
connector { // <1>
name: broker
role: route-container
host: 198.51.100.1
port: 61617
saslMechanisms: ANONYMOUS
}
linkRoute { // <2>
prefix: b2
direction: in
connection: broker
}
linkRoute { // <3>
prefix: b2
direction: out
connection: broker
}
----
<1> The outgoing connection from the router to broker `B2`. The `route-container` role enables the router to connect to an external AMQP container (in this case, a broker).
<2> The incoming link route for receiving links from client senders. Any sender with a target whose address begins with `b2` will be routed to broker `B2` using the `broker` connector.
<3> The outgoing link route for sending links to client receivers. Any receivers whose source address begins with `b2` will be routed to broker `B2` using the `broker` connector.
--
This configuration enables router `Ra` to advertise itself as a valid destination for targets and sources starting with `b2`. It also enables the router to connect to broker `B2`, and to route links to and from queues starting with the `b2` prefix.
[NOTE]
====
While not required, routers `Rp` and `Rb` should also have the same configuration.
====
==== How the Client Receives Messages
By using the configured link route, client `C1` can receive messages from broker `B2` even though they are on different networks.
Router `Ra` establishes a connection to broker `B2`. Once the connection is open, `Ra` tells the other routers (`Rp` and `Rb`) that it is a valid destination for link routes to the `b2` prefix. This means that sender and receiver links attached to `Rb` or `Rp` will be routed along the shortest path to `Ra`, which then routes them to broker `B2`.
To receive messages from the `b2.event-queue` on broker `B2`, client `C1` attaches a receiver link with a source address of `b2.event-queue` to its local router, `Rb`. Because the address matches the `b2` prefix, `Rb` routes the link to `Rp`, which is the next hop in the route to its destination. `Rp` routes the link to `Ra`, which routes it to broker `B2`. Client `C1` now has a receiver established, and it can begin receiving messages.
[NOTE]
====
If broker `B2` is unavailable for any reason, router `Ra` will not advertise itself as a destination for `b2` addresses. In this case, routers `Rb` and `Rp` will reject link attaches that should be routed to broker `B2` with an error message indicating that there is no route available to the destination.
====
[id='router-address-pattern-matching']
=== Pattern Matching for Addresses
In some router configuration scenarios, you might need to use pattern matching to match a range of addresses rather than a single, literal address. Address patterns match any address that corresponds to the pattern.
An address pattern is a sequence of tokens (typically words) that are delimited by either `.` or `/` characters. They also can contain special wildcard characters that represent words:
* `*` represents exactly one word
* `#` represents zero or more words
.Address Pattern
====
This address contains two tokens, separated by the `/` delimiter:
`my/address`
====
.Address Pattern with Wildcard
====
This address contains three tokens. The `*` is a wildcard, representing any single word that might be between `my` and `address`:
`my/*/address`
====
The following table shows some address patterns and examples of the addresses that would match them:
[options="header"]
|===
| This pattern... | Matches... | But not...
a| `news/*`
a| `news/europe`
`news/usa`
a| `news`
`news/usa/sports`
a| `news/#`
a| `news`
`news/europe`
`news/usa/sports`
a| `europe`
`usa`
a| `news/europe/#`
a| `news/europe`
`news/europe/sports`
`news/europe/politics/fr`
a| `news/usa`
`europe`
a| `news/*/sports`
a| `news/europe/sports`
`news/usa/sports`
a| `news`
`news/europe/fr/sports`
|===