AMQP 1.0
AMQP 1.0 is supported natively since RabbitMQ 4.0.
Version Negotiation
RabbitMQ natively supports both AMQP 1.0 and AMQP 0.9.1 out of the box, without requiring any additional plugins.
By default, RabbitMQ listens on port 5672, accepting connections for both AMQP 1.0 and AMQP 0.9.1.
After establishing a TCP or TLS connection and before sending any AMQP frames, the client sends a protocol header indicating whether it wants to use AMQP 1.0 or AMQP 0.9.1, as outlined in Section 2.2 Version Negotiation.
For AMQP 1.0 connections, RabbitMQ requires the use of Simple Authentication and Security Layer (SASL), as described in Section 5.3 SASL. If the client does not use SASL, RabbitMQ will reject the connection, as illustrated in Figure 2.13: Protocol ID Rejection Example.
Protocol Interoperability
RabbitMQ supports publishing and consuming messages across different protocols, which requires protocol conversions.
When a message is published using AMQP 1.0, all target queue types (classic queues, quorum queues, and streams) store the message in its original AMQP 1.0 format. If the message is later consumed using AMQP 1.0, no protocol conversion is necessary. Additionally, as mandated by the AMQP 1.0 specification, RabbitMQ ensures the immutability of the bare message. This allows clients to set message hashes, checksums, and digital signatures not only over the message body but also over the properties and application-properties sections.
Virtual Hosts
RabbitMQ supports logical multi-tenancy with virtual hosts.
If no virtual host was explicitly specified by the connecting application, the connection use the default_vhost
configured in rabbitmq.conf:
default_vhost = /
AMQP 1.0 clients can connect to a different virtual host by prefixing the value of the hostname
field in the open
frame with vhost:
.
For example, to connect to a virtual host called tenant-1
, the client sets the hostname
field to vhost:tenant-1
.
Addresses
An AMQP 1.0 address determines where a message is sent to or consumed from. What internal object an AMQP address refers to and how an AMQP address is resolved is not defined by the AMQP 1.0 specification. Different AMQP 1.0 brokers can choose to interprete the provided address differently.
RabbitMQ implements the powerful and flexible AMQ 0.9.1 model comprising exchanges, queues, and bindings. Therefore, AMQP clients talking to RabbitMQ send messages to exchanges and consume messages from queues. Hence, the AMQP addresses that RabbitMQ understands and resolves contain exchange names, queue names, and routing keys.
RabbitMQ 4.0 introduces a new RabbitMQ specific AMQP address format, v2. The old RabbitMQ 3.x address format is referred to as v1.
AMQP clients should use address format v2.
Address format v1 is deprecated in RabbitMQ 4.0 and will be unsupported in a future RabbitMQ version.
Whether format v1 is still supported is determined by the deprecated feature flag amqp_address_v1
whose deprecation phase is permitted_by_default
in RabbitMQ 4.0.
Address v2
This section defines the new v2 address formats.
Target Address v2
The possible v2 target address formats are:
/exchanges/:exchange/:routing-key
/exchanges/:exchange
/queues/:queue
<null>
The first three formats are strings.
The 1st format /exchanges/:exchange/:routing-key
causes all messages on the given link to be sent to exchange :exchange
with routing key :routing-key
.
The 2nd format /exchanges/:exchange
causes all messages on the given link to be sent to exchange :exchange
with the empty routing key ""
.
This is useful for exchange types that ignore the routing key, such as the fanout exchange or the headers exchange.
Setting the default exchange ""
in either of the first two formats is disallowed. Instead, use the 3rd format.
The 3rd format /queues/:queue
causes all messages on the given link to be sent to queue :queue
.
The queue must exist.
Internally, this queue target still uses the default exchange. Hence, the user needs write permissions to exchange amq.default
.
The first 3 formats require the target address to be the same for all messages on the given link. If different exchanges, routing keys, or queues need to be set for different messages on the same link, use the 4th format.
The 4th format is the AMQP null value.
As explained in the AMQP extension Using the AMQP Anonymous Terminus for Message Routing,
each message's to
field of the properties section must be set.
The allowed to
address strings must have the same format, i.e. one of
/exchanges/:exchange/:routing-key
/exchanges/:exchange
/queues/:queue
where the exchange must exist.
If a message cannot be routed, for example, because no queue is bound to the target exchange,
RabbitMQ settles the message with the released
outcome.
If a publishing application needs to publish (send) messages to
- a single destination: prefer one of the first three string formats over the 4th (null) format as the first three formats provide slightly better performance
- a small number of different destinations: prefer opening one link per destination with one of the first three formats
- a large number of different destinations: prefer the 4th (null) format defining each destination in the
to
field
Source Address v2
The only valid v2 source address string format is
/queues/:queue
where clients consume messages from queue :queue
.
The queue must exist.
Percent-encoding
Address format v2 requires exchange names, routing keys, and queue names to be percent-encoded according to RFC 3986.
For example, a client that wants to send to exchange amq.direct
with routing key my-routing_key/123
must use target address /exchanges/amq.direct/my-routing_key%2F123
.
Note that percent-encoding in address format v2 must be applied to all AMQP fields that require an address
:
address
field in targetaddress
field in sourceto
field in message propertiesreply-to
field in message properties
Address v1
This section lists the deprecated v1 address string formats.
Target Address v1
/exchange/:exchange/:routing-key
/exchange/:exchange
/topic/:routing-key
/amq/queue/:queue
/queue/:queue
:queue
/queue
The 1st format /exchange/:exchange/:routing-key
causes all messages on the given link to be sent to exchange :exchange
with routing key :routing-key
.
The equivalent v2 format is /exchanges/:exchange/:routing-key
.
The 2nd format /exchange/:exchange
causes all messages on the given link to be sent to exchange :exchange
while the routing key can optionally be provided in the
message subject
field of the properties section.
In v2, defining different routing keys per message requires setting the target address to the AMQP null value and the message to
field to /exchanges/:exchange/:routing-key
.
The 3rd format /topic/:routing-key
causes all messages on the given link to be sent to RabbitMQ's default topic exchange called amq.topic
with topic routing-key
.
In v2, use /exchanges/amq.topic/:routing-key
.
The 4th format /amq/queue/:queue
causes all messages on the given link to be sent to queue :queue
(to be more precise, internally, to the default exchange with routing key :queue
).
Queue :queue
must exist.
In v2, use /queues/:queue
.
The 5th format /queue/:queue
has similar semantics to the 4th format.
However, RabbitMQ will auto declare queue :queue
, i.e. create such a queue if it doesn't exist.
The queue is never auto deleted by RabbitMQ.
In v2, use /queues/:queue
.
RabbitMQ 4.0 allows AMQP clients to create RabbitMQ topologies including queues with client defined queue types, properties, and arguments.
Hence, there is no need for RabbitMQ itself to auto declare a specific queue for a given queue target address format.
The 6th format :queue
is redundant to the 5th format.
The 7th format causes the message to be sent to the queue provided in the message subject
field.
In v2, to send messages to different queues, set the target address to the AMQP null value and the message to
field to /queues/:queue
.
Source Address v1
/exchange/:exchange/:binding-key
/topic/:binding-key
/amq/queue/:queue
/queue/:queue
:queue
The 1st format /exchange/:exchange/:binding-key
causes RabbitMQ to declare a queue and bind that queue to exchange :exchange
with binding key :binding-key
.
Messages are then consumed from that queue.
The 2nd format /topic/:binding-key
causes RabbitMQ to declare a queue and bind that queue to the default topic exchange amq.topic
with topic filter :binding-key
.
Messages are then consumed from that queue.
The 3rd format /amq/queue/:queue
causes RabbitMQ to consume from queue :queue
.
Queue :queue
must exist.
The 4th format /queue/:queue
causes RabbitMQ to declare a queue :queue
and consume from that queue.
The 5th format :queue
is redundant to the 4th format.
As explained previously, RabbitMQ 4.0 allows AMQP clients to create RabbitMQ topologies including queues with client defined queue types, properties, and arguments.
Hence, there is no need for RabbitMQ itself to auto declare a specific queue for a given queue source address format.
In v2, clients should first declare their own queues and bindings, and then attach with source address /queues/:queue
which causes the client to consume from that queue.
Outcomes
An outcome indicates the result of delivery (message) processing at the receiver.
The following table describes the outcomes when the client is the sender/publisher/producer with RabbitMQ acting as the receiver:
AMQP 1.0 Outcome | Equivalent AMQP 0.9.1 Frame | Description |
---|---|---|
Accepted | basic.ack | All queues the message was routed to have accepted the message. For example for quorum queues, this means a majority of quorum queue replicas have written the message to disk. The publisher can therefore forget/delete the message. |
Rejected | basic.nack | At least one queue the message was routed to rejected the message. This happens when the queue length is exceeded and the queue's overflow behaviour is set to reject-publish or when a target classic queue is unavailable.RabbitMQ also rejects messages as specified in Using the AMQP Anonymous Terminus for Message Routing, for example if a message's to field of the properties section contains an invalid address or defines a non-existing exchange. |
Released | basic.return (followed by basic.ack or basic.nack ) | RabbitMQ could not route the message to any queue. This indicates a topology misconfiguration, for example when no matching queue is bound to the target exchange. |
Modified | Currently, RabbitMQ does not settle a message with the modified outcome. |
The following table describes the outcomes when the client is the receiver/consumer with RabbitMQ acting as the sender:
AMQP 1.0 Outcome | Equivalent AMQP 0.9.1 Frame | Description |
---|---|---|
Accepted | basic.ack | The consumer successfully processed the message. RabbitMQ can therefore delete the message. |
Rejected | basic.nack or basic.reject with requeue=false | The consumer indicates that the message is invalid and unprocessable. RabbitMQ dead letters the message (or drops the message if dead lettering is not configured). |
Released | basic.nack or basic.reject with requeue=true | The consumer did not process the message. RabbitMQ requeues the message. The message will be delivered to the same or a different consumer. |
Modified | The consumer did not process the message, but modified message annotations. If undeliverable-here=true , RabbitMQ dead letters the message (or drops the message if dead lettering is not configured).If undeliverable-here=false , RabbitMQ requeues the message.See below for more information. |
AMQP 1.0 vs. AMQP 0.9.1
As the name suggests, AMQP 1.0 is the more modern protocol. It is an ISO/IEC 19464 and OASIS standard, whereas AMQP 0.9.1 is not an official standard. For a more detailed comparison of the protocols, refer to our AMQP 1.0 blog posts.
Choosing the right protocol depends on several factors, including:
- Feature Requirements: Whether you need specific features of AMQP 1.0 or AMQP 0.9.1.
- Interoperability: If interoperability with other message brokers is important, note that more brokers support AMQP 1.0 than AMQP 0.9.1.
- Client Library Availability: Whether supported client libraries are available for your programming language.
AMQP 1.0 Features
This section lists features that RabbitMQ supports exclusively in AMQP 1.0, which are not available in AMQP 0.9.1:
- Fine Granular Flow Control as explained in the blog post Ten Benefits of AMQP 1.0 Flow Control:
- A consuming client application can dynamically adjust and prioritize how many messages it wants to receive from specific source queues.
- Safe and efficient use of a single AMQP connection for both publishing and consuming.
- When one target queue is overloaded, publishers can continue sending at high speed to other target queues, and consumers can continue receiving at high speed from other source queues on the same AMQP connection.
- Consumers can be stopped or paused and later resumed.
- Graceful handoff from one single active consumer to the next, while maintaining message order.
- The source queue can efficiently inform the consumer about an approximate number of available messages.
- Queue Locality: RabbitMQ can provide up-to-date queue topology and leader information to clients.
- For example, the RabbitMQ AMQP 1.0 Java client can leverage this information by trying to consume "locally" from a RabbitMQ node that hosts a queue replica and trying to publish "locally" to a node that hosts the queue leader.
- This can result in lower intra-cluster traffic, reducing latency and increasing throughput.
- Sender Settle Mode
mixed
: Allows a publisher to decide on a per-message basis whether to receive confirmations from the broker. - Modified Outcome: Allows a quorum queue consumer to add and modify message annotations when requeueing or dead lettering a message.
- Well defined types
- Better defined message headers
- Enhanced Message Integrity: Clients can set message hashes, checksums, and digital signatures not only over the message body but also over the properties and application-properties sections, as the bare message is immutable.
- Stream Message Fidelity: No loss of headers fidelity when storing or retrieving a message from a stream, since streams store messages in AMQP 1.0 encoded format.
AMQP 0.9.1 Features
This section lists features that RabbitMQ supports exclusively in AMQP 0.9.1, which are currently not available in AMQP 1.0:
- Transactions: AMQP 0.9.1 provides limited support, whereas AMQP 1.0 currently does not support transactions (as listed in the limitations).
- Direct Reply-to: While AMQP 1.0 clients can still perform Remote Procedure Calls (RPCs) by declaring a reply queue, the Direct Reply-to feature is exclusive to AMQP 0.9.1.
- OAuth 2.0 Token Refresh: AMQP 0.9.1 clients can renew tokens via method update-secret. Token renewal is currently unsupported in AMQP 1.0. When a token expires, the AMQP 1.0 connection will be closed.
- AMQP 0.9.1 Channel Interceptor: Plugins, such as the Sharding Plugin, that intercept and modify frames are currently only supported for AMQP 0.9.1.
- Metrics delivery including message rates via the Management UI: As documented in the Deprecation Announcements, Prometheus should be used.
- Inspecting AMQP 0.9.1 Channel Details: This can be done in the Management UI or using CLI tools. AMQP 1.0 session and link details currently cannot be inspected.
Clients
Any AMQP 1.0 client should be able to communicate with RabbitMQ. The RabbitMQ team at Broadcom has developed two AMQP 1.0 client libraries specifically for RabbitMQ:
See the AMQP client libraries page for more information.
Currently, the AMQP 0.9.1 client ecosystem is more extensive, with a greater number of AMQP 0.9.1 client libraries supported by the RabbitMQ team at Broadcom.
Limitations
RabbitMQ does not support the following AMQP 1.0 features:
- "Suspending" or "resuming" a link including
- Figure 2.8: Link Recovery
- "exactly once" delivery
- resuming deliveries
- Terminus Expiry Policy
aborted
field in transfer framedynamic
field in source and target: clients can instead dynamically create server topologies (exchanges, queues, bindings) via HTTP over AMQP prior to attaching a link.- Transactions
- Protocol Header for TLS Security Layer (Figure 5.1) including a protocol id of two. Instead, RabbitMQ runs a pure TLS server and therefore implements section 5.2.1.
Modified Outcome
Modifying message annotations with the modified outcome is supported in quorum queues, but not in classic queues. Modifying a message in a stream doesn't make sense given that a stream is an immutable log.
If field undeliverable-here
is
true
, classic queues and quorum queues will dead letter the message. If dead lettering is not configured, the message will be discarded.false
, classic queues and quorum queues will requeue the message.
The behaviour of undeliverable-here
may change in a future RabbitMQ version.
For example, if undeliverable-here = true
, instead of dead lettering the message, in the future,
queues might requeue the message while ensuring that the message is not redelivered to the modifying link endpoint.