|
| 1 | +--- |
| 2 | +title: Alternate Exchanges |
| 3 | +--- |
| 4 | + |
| 5 | +<!-- |
| 6 | +Copyright (c) 2005-2025 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. |
| 7 | +
|
| 8 | +All rights reserved. This program and the accompanying materials |
| 9 | +are made available under the terms of the under the Apache License, |
| 10 | +Version 2.0 (the "License”); you may not use this file except in compliance |
| 11 | +with the License. You may obtain a copy of the License at |
| 12 | +
|
| 13 | +https://www.apache.org/licenses/LICENSE-2.0 |
| 14 | +
|
| 15 | +Unless required by applicable law or agreed to in writing, software |
| 16 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 17 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 18 | +See the License for the specific language governing permissions and |
| 19 | +limitations under the License. |
| 20 | +--> |
| 21 | + |
| 22 | +import Tabs from '@theme/Tabs'; |
| 23 | +import TabItem from '@theme/TabItem'; |
| 24 | + |
| 25 | +# Alternate Exchanges |
| 26 | + |
| 27 | +## Overview {#overview} |
| 28 | + |
| 29 | +It is sometimes desirable to let clients handle messages |
| 30 | +that an exchange was unable to route (i.e. either because |
| 31 | +there were no bound queues or no matching |
| 32 | +bindings). Typical examples of this are |
| 33 | + |
| 34 | + * detecting when clients accidentally or maliciously publish messages that cannot be routed |
| 35 | + * "or else" routing semantics where some messages are handled specially and the rest by a generic handler |
| 36 | + |
| 37 | +Alternate Exchange ("AE") is a feature that addresses these use cases. |
| 38 | + |
| 39 | +## How to Define an Alternate Exchange {#define} |
| 40 | + |
| 41 | +For any given exchange except for the default one, an AE can be defined by clients using |
| 42 | +[policies](./policies). This is the recommended option |
| 43 | +as policies are significantly simplify changes to such options (e.g. during |
| 44 | +upgrades). |
| 45 | + |
| 46 | +In modern RabbitMQ versions, the default exchange is a special-cased convention in the code |
| 47 | +and not a "real" exchange. Therefore it does not support the alternate exchange feature. |
| 48 | + |
| 49 | +Alternatively, optional exchange arguments can be provided by client |
| 50 | +at exchange declaration time. |
| 51 | +In the case where both policy and arguments specify an AE, the one |
| 52 | +specified in arguments overrules the one specified in policy. |
| 53 | + |
| 54 | +### Configuration Using a Policy {#define-using-policy} |
| 55 | + |
| 56 | +This is the recommended way of defining alternate exchanges. |
| 57 | + |
| 58 | +To specify an AE using policy, add the key 'alternate-exchange' |
| 59 | +to a policy definition and make sure that the policy matches the exchange(s) |
| 60 | +that need the AE defined. For example: |
| 61 | + |
| 62 | +<Tabs groupId="examples"> |
| 63 | +<TabItem value="bash" label="rabbitmqctl with bash" default> |
| 64 | +```bash |
| 65 | +rabbitmqctl set_policy AE "^my-direct$" '{"alternate-exchange":"my-ae"}' --apply-to exchanges |
| 66 | +``` |
| 67 | +</TabItem> |
| 68 | + |
| 69 | +<TabItem value="rabbitmqadmin" label="rabbitmqadmin with bash"> |
| 70 | +```bash |
| 71 | +rabbitmqadmin policies declare \ |
| 72 | + --name "AE" \ |
| 73 | + --pattern "^my-direct$" \ |
| 74 | + --definition '{"alternate-exchange":"my-ae"}' \ |
| 75 | + --apply-to "exchanges" |
| 76 | +``` |
| 77 | +</TabItem> |
| 78 | + |
| 79 | +<TabItem value="PowerShell" label="rabbitmqctl with PowerShell"> |
| 80 | +```PowerShell |
| 81 | +rabbitmqctl.bat set_policy AE "^my-direct$" "{""alternate-exchange"":""my-ae""}" --apply-to exchanges |
| 82 | +``` |
| 83 | +</TabItem> |
| 84 | + |
| 85 | +<TabItem value="rabbitmqadmin-PowerShell" label="rabbitmqadmin with PowerShell"> |
| 86 | +```PowerShell |
| 87 | +rabbitmqadmin.exe policies declare ^ |
| 88 | + --name "AE" ^ |
| 89 | + --pattern "^my-direct$" ^ |
| 90 | + --definition "{""alternate-exchange"":""my-ae""}" ^ |
| 91 | + --apply-to "exchanges" |
| 92 | +``` |
| 93 | +</TabItem> |
| 94 | +</Tabs> |
| 95 | + |
| 96 | +This will apply an AE of "my-ae" to the exchange called |
| 97 | +"my-direct". Policies can also be defined using the management |
| 98 | +plugin, see the [policy documentation](./policies) for more details. |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +### Configuration Using Client-provided Arguments {#define-using-arguments} |
| 103 | + |
| 104 | +This way of defining an alternate exchange is discouraged. Consider |
| 105 | +using a policy instead (see above). |
| 106 | + |
| 107 | +When creating an exchange the name of an AE can be |
| 108 | +optionally supplied in the `exchange.declare` |
| 109 | +method's `arguments` table by specifying a key |
| 110 | +of 'alternate-exchange' and a string value containing the name. |
| 111 | + |
| 112 | +When an AE has been specified, in addition to the usual |
| 113 | +`configure` permission on the declared exchange, |
| 114 | +the user needs to have `read` permissions on that |
| 115 | +exchange and `write` permissions on the AE. |
| 116 | + |
| 117 | +For example: |
| 118 | + |
| 119 | +```java |
| 120 | +Map<String, Object> args = new HashMap<String, Object>(); |
| 121 | +args.put("alternate-exchange", "my-ae"); |
| 122 | +channel.exchangeDeclare("my-direct", "direct", false, false, args); |
| 123 | +channel.exchangeDeclare("my-ae", "fanout"); |
| 124 | +channel.queueDeclare("routed"); |
| 125 | +channel.queueBind("routed", "my-direct", "key1"); |
| 126 | +channel.queueDeclare("unrouted"); |
| 127 | +channel.queueBind("unrouted", "my-ae", ""); |
| 128 | +``` |
| 129 | + |
| 130 | +In the above fragment of Java code we create a direct |
| 131 | +exchange 'my-direct' that is configured with an AE called |
| 132 | +'my-ae'. The latter is declared as a fanout exchange. We |
| 133 | +bind one queue 'routed' to 'my-direct' with a binding key |
| 134 | +of 'key1', and a queue 'unrouted' to 'my-ae'. |
| 135 | + |
| 136 | + |
| 137 | +## How Alternate Exchanges Work {#how-it-works} |
| 138 | + |
| 139 | +Whenever a message published to an exchange with a configured AE cannot be routed |
| 140 | +to any queue, the channel re-publishes the message to the specified AE |
| 141 | +instead. If that AE does not exist then a warning is logged. If |
| 142 | +an AE cannot route a message, it in turn publishes the message |
| 143 | +to its AE, if it has one configured. This process continues |
| 144 | +until either the message is successfully routed, the end of the |
| 145 | +chain of AEs is reached, or an AE is encountered which has |
| 146 | +already attempted to route the message. |
| 147 | + |
| 148 | +For example if we publish a message to 'my-direct' with a |
| 149 | +routing key of 'key1' then that message is routed to the |
| 150 | +'routed' queue, in accordance with the standard AMQP |
| 151 | +behaviour. However, when publishing a message to |
| 152 | +'my-direct' with a routing key of 'key2', rather than |
| 153 | +being discarded the message is routed via our configured |
| 154 | +AE to the 'unrouted' queue. |
| 155 | + |
| 156 | +The behaviour of an AE purely pertains to routing. If a message |
| 157 | +is routed via an AE it still counts as routed for the purpose of |
| 158 | +the 'mandatory' flag, and the message is otherwise unchanged. |
0 commit comments