AMQP

Advanced Message Queuing Protocol

Protocol Specification

Version 0-10-transportsig-draft June 2007 [amq-spec]

A General-Purpose Middleware Standard

Technical Contributors:

Sanjay Aiyagari Cisco Systems Shahrokh Sadjadi Cisco Systems
Matthew Arrot Twist Process Innovations Rafael Schloming Red Hat
Mark Atwell JPMorgan Chase Steven Shaw JPMorgan Chase
Jason Brome Envoy Technologies Gordon Sim Red Hat
Alan Conway Red Hat Martin Sustrik iMatix Corporation
Robert Greig JPMorgan Chase Carl Trieloff Red Hat
Pieter Hintjens iMatix Corporation Kim van der Riet Red Hat
John O'Hara JPMorgan Chase Steve Vinoski IONA Technologies
Martin Ritchie JPMorgan Chase

Copyright Notice

© Copyright JPMorgan Chase & Co., Cisco Systems, Inc., Envoy Technologies, Inc., iMatix Corporation, IONA Technologies, Red Hat, Inc., TWIST Process Innovations, and 29West 2006. All rights reserved.

License

JPMorgan Chase & Co., Cisco Systems, Inc., Envoy Technologies, Inc., iMatix Corporation, IONA Technologies, Red Hat, Inc., TWIST Process Innovations, and 29West (collectively, the "Authors") each hereby grants to you a worldwide, perpetual, royalty-free, nontransferable, nonexclusive license to (i) copy, display, distribute and implement the Advanced Messaging Queue Protocol ("AMQP") Specification and (ii) the Licensed Claims that are held by the Authors, all for the purpose of implementing the Advanced Messaging Queue Protocol Specification. Your license and any rights under this Agreement will terminate immediately without notice from any Author if you bring any claim, suit, demand, or action related to the Advanced Messaging Queue Protocol Specification against any Author. Upon termination, you shall destroy all copies of the Advanced Messaging Queue Protocol Specification in your possession or control.

As used hereunder, "Licensed Claims" means those claims of a patent or patent application, throughout the world, excluding design patents and design registrations, owned or controlled, or that can be sublicensed without fee and in compliance with the requirements of this Agreement, by an Author or its affiliates now or at any future time and which would necessarily be infringed by implementation of the Advanced Messaging Queue Protocol Specification. A claim is necessarily infringed hereunder only when it is not possible to avoid infringing it because there is no plausible non-infringing alternative for implementing the required portions of the Advanced Messaging Queue Protocol Specification. Notwithstanding the foregoing, Licensed Claims shall not include any claims other than as set forth above even if contained in the same patent as Licensed Claims; or that read solely on any implementations of any portion of the Advanced Messaging Queue Protocol Specification that are not required by the Advanced Messaging Queue Protocol Specification, or that, if licensed, would require a payment of royalties by the licensor to unaffiliated third parties. Moreover, Licensed Claims shall not include (i) any enabling technologies that may be necessary to make or use any Licensed Product but are not themselves expressly set forth in the Advanced Messaging Queue Protocol Specification (e.g., semiconductor manufacturing technology, compiler technology, object oriented technology, networking technology, operating system technology, and the like); or (ii) the implementation of other published standards developed elsewhere and merely referred to in the body of the Advanced Messaging Queue Protocol Specification, or (iii) any Licensed Product and any combinations thereof the purpose or function of which is not required for compliance with the Advanced Messaging Queue Protocol Specification. For purposes of this definition, the Advanced Messaging Queue Protocol Specification shall be deemed to include both architectural and interconnection requirements essential for interoperability and may also include supporting source code artifacts where such architectural, interconnection requirements and source code artifacts are expressly identified as being required or documentation to achieve compliance with the Advanced Messaging Queue Protocol Specification.

As used hereunder, "Licensed Products" means only those specific portions of products (hardware, software or combinations thereof) that implement and are compliant with all relevant portions of the Advanced Messaging Queue Protocol Specification.

The following disclaimers, which you hereby also acknowledge as to any use you may make of the Advanced Messaging Queue Protocol Specification:

THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION.

The name and trademarks of the Authors may NOT be used in any manner, including advertising or publicity pertaining to the Advanced Messaging Queue Protocol Specification or its contents without specific, written prior permission. Title to copyright in the Advanced Messaging Queue Protocol Specification will at all times remain with the Authors.

No other rights are granted by implication, estoppel or otherwise.

Upon termination of your license or rights under this Agreement, you shall destroy all copies of the Advanced Messaging Queue Protocol Specification in your possession or control.

Status of this Document

"JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the Octagon Symbol are trademarks of JPMorgan Chase & Co.

IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.

IONA, IONA Technologies, and the IONA logos are trademarks of IONA Technologies PLC and/or its subsidiaries.

LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered trademarks of Red Hat, Inc. in the US and other countries.

Java, all Java-based trademarks and OpenOffice.org are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

Other company, product, or service names may be trademarks or service marks of others.

Table of Contents

§ 1 Overview

§ 1.1 Goals of This Document

This document defines a networking protocol, the Advanced Message Queuing Protocol (AMQP), which enables conforming client applications to communicate with conforming messaging middleware services. To fully achieve this we also define the normative behaviour of the messaging middleware service.

We address a technical audience with some experience in the domain, and we provide sufficient specifications and guidelines that a suitably skilled engineer can construct conforming solutions in any modern programming language or hardware platform.

§ 1.2 Patents

A concious design objective of AMQP was to base it on concepts taken from existing, unencumbered, widely implemented standards such those published by the Internet Engineering Task Force (IETF) or the World Wide Web Consortium (W3C).

Consequently, we believe it is possible to create AMQP implementations using only well known techniques such as those found in existing Open Source networking and email routing software or which are otherwise well-known to technology experts.

§ 1.3 Summary

§ 1.3.1 What is AMQP?

The Advanced Message Queuing Protocol (AMQP) creates full functional interoperability between conforming clients and messaging middleware servers (also called "brokers").

§ 1.3.2 Why AMQP?

Our goal is to enable the development and industry-wide use of standardised messaging middleware technology that will lower the cost of enterprise and systems integration and provide industrial-grade integration services to a broad audience.

It is our aim that through AMQP messaging middleware capabilities may ultimately be driven into the network itself, and that through the pervasive availability of messaging middleware new kinds of useful applications may be developed.

§ 1.3.3 Scope of AMQP

To enable complete interoperability for messaging middleware requires that both the networking protocol and the semantics of the broker services are sufficiently specified.

AMQP, therefore, defines both the network protocol and the broker services through:

  1. A defined set of messaging capabilities called the "Advanced Message Queuing Protocol Model" (AMQP Model). The AMQP Model consists of a set of components that route and store messages within the broker service, plus a set of rules for wiring these components together.

  2. A network wire-level protocol, AMQP, that lets client applications talk to the broker and interact with the AMQP Model it implements.

One can partially imply the semantics of the server from the AMQP protocol specifications but we believe that an explicit description of these semantics helps the understanding of the protocol.

§ 1.3.4 The Advanced Message Queuing Protocol

TODO: edit for flow and correctness

§ 1.3.4.1 The AMQP Model

We define the server's semantics explicitly, since interoperability demands that these be the same in any given server implementation.

The AMQP Model thus specifies a modular set of components and standard rules for connecting these.

There are three main types of component, which are connected into processing chains in the server to create the desired functionality:

  1. The "exchange" receives messages from publisher applications and routes these to "message queues", based on arbitrary criteria, usually message properties or content

  2. The "message queue" stores messages until they can be safely processed by a consuming client application (or multiple applications)

  3. The "binding" defines the relationship between a message queue and an exchange and provides the message routing criteria

Using this model we can emulate the classic middleware concepts of store-and-forward queues and topic subscriptions trivially. We can also expresses less trivial concepts such as content-based routing, message queue forking, and on-demand message queues.

In very gross terms, an AMQP server is analogous to an email server, with each exchange acting as a message transfer agent, and each message queue as a mailbox. The bindings define the routing tables in each transfer agent. Publishers send messages to individual transfer agents, which then route the messages into mailboxes. Consumers take messages from mailboxes.

In many pre-AMQP middleware system, by contrast, publishers send messages directly to individual mailboxes (in the case of store-and-forward queues), or to mailing lists (in the case of topic subscriptions).

The difference is that when the rules connecting message queues to exchanges are under control of the architect (rather than embedded in code), it becomes possible to do interesting things, such as define a rule that says, "place a copy of all messages containing such-and-such a header into this message queue".

The design of the AMQP Model was driven by these main requirements:

  1. To support the semantics required by the financial services industry

  2. To provide the levels of performance required by the financial services industry

  3. To be easily extended for new kinds of message routing and queueing

  4. To permit the server's specific semantics to be programmed by the application, via the protocol

  5. To be flexible yet simple.

§ 1.3.4.2 The AMQP Protocol

The AMQP protocol is a binary protocol with modern features: it is multi-channel, negotiated, asynchronous, secure, portable, neutral, and efficient.

AMQP is usefully split into two layers:

    +--------------------The AMQP Model--------------------+
    |                                                      |
    |    Messages   Streaming   Basic   File Transfer      |
    |                                                      |
    |  Queues   Exchanges   Access Control   Transactions  |
    |                                                      |
    |                     Sessions                         |
    |                                                      |
    +------------------------------------------------------+

    +-------------------The AMQP Protocol------------------+
    |                                                      |
    |      Sessions    Content    Data Representation      |
    |                                                      |
    |           Error Handling    Heart-beating            |
    |                                                      |
    |                 Framing    Channels                  |
    |                                                      |
    +------------------------------------------------------+
TODO: edit for flow and correctness

The functional layer defines a set of commands (grouped into logical classes of functionality) that do useful work on behalf of the application.

The transport layer that carries these methods from application to server, and back, and which handles channel multiplexing, framing, content encoding, heart-beating, data representation, and error handling.

One could replace the transport layer with arbitrary transports without changing the application-visible functionality of the protocol. One could also use the same transport layer for different high-level protocols.

The design of the AMQP Model was driven by these requirements:

  1. To guarantee interoperability between conforming implementations

  2. To provide explicit control over the quality of service

  3. To support any middleware domain: messaging, file transfer, streaming, RPC, etc

  4. To accommodate existing messaging API standards (for example, Sun's JMS)

  5. To be consistent and explicit in naming

  6. To allow complete configuration of server wiring via the protocol

  7. To use a command notation that maps easily into application-level API's

  8. To be clear, so each operation does exactly one thing.

TODO: edit for flow and correctness

The design of AMQP transport layer was driven by these main requirements, in no particular order:

  1. To be compact, using a binary encoding that packs and unpacks rapidly

  2. To handle messages of any size without significant limit

  3. To permit zero-copy data transfer (e.g. remote DMA)

  4. To carry multiple channels across a single connection

  5. To be long-lived, with no significant in-built limitations

  6. To allow asynchronous command pipe-lining

  7. To be easily extended to handle new and changed needs

  8. To be forward compatible with future versions

  9. To be repairable, using a strong assertion model

  10. To be neutral with respect to programming languages

  11. To fit a code generation process.

Note: This section should be updated to include the features from the request/response transport.

§ 1.3.5 Scales of Deployment

The scope of AMQP covers different levels of scale, roughly as follows:

  1. Developer/casual use: 1 server, 1 user, 10 message queues, 1 message per second

  2. Production application: 2 servers, 10-100 users, 10-50 message queues, 10 messages per second (36K messages/hour)

  3. Departmental mission critical application: 4 servers, 100-500 users, 50-100 message queues, 100 messages per second (360K/hour)

  4. Regional mission critical application: 16 servers, 500-2,000 users, 100-500 message queues and topics, 1000 messages per second(3.6M/hour)

  5. Global mission critical application: 64 servers, 2K-10K users, 500-1000 message queues and topics, 10,000 messages per second(36M/hour)

  6. Market data (trading): 200 servers, 5K users, 10K topics, 100K messages per second (360M/hour)

As well as volume, the latency of message transfer can be highly important. For instance, market data becomes worthless very rapidly. Implementations may differentiate themselves by providing differing Quality of Service or Manageability Capabilities whilst remaining fully compliant with this specification.

§ 1.3.6 Functional Scope

We want to support a variety of messaging architectures:

  1. Store-and-forward with many writers and one reader

  2. Transaction distribution with many writers and many readers

  3. Publish-subscribe with many writers and many readers

  4. Content-based routing with many writers and many readers

  5. Queued file transfer with many writers and many readers

  6. Point-to-point connection between two peers

  7. Market data distribution with many sources and many readers.

§ 1.4 Organisation of This Document

TODO: update this before release

The document is divided into five chapters, most of which are designed to be read independently according to your level of interest:

  1. "Overview" (this chapter). Read this chapter for an introduction

  2. "General Architecture", in which we describe the architecture and overall design of AMQP. This chapter is intended to help systems architects understand how AMQP works

  3. "Functional Specifications", in which we define how applications work with AMQP. This chapter consists of a readable discussion, followed by a detailed specification of each protocol command, intended as a reference for implementers. Before reading this chapter you should read the General Architecture

  4. "Technical Specifications", in which we define how the AMQP transport layer works. This chapter consists of a short discussion, followed by a detailed specification of the wire-level constructs, intended as a reference for implementers. You can read this chapter by itself if you want to understand how the wire-level protocol works (but not what it is used for)

  5. "Conformance Tests", in which we explain the conformance tests, which assert that an AMQP server conforms to the functional and technical specifications defined in this document. You can read this chapter by itself

  6. "Background", in which we state and analyse the scope and requirements of the AMQP standard and describe some of the underlying motivations behind the most important features of the protocol. This chapter comes last because it is not part of the knowledge needed to write an AMQP implementation, but it does provide useful background understanding. Note that the specification chapters include statements of key requirements, without analysis.

§ 1.5 Conventions

§ 1.5.1 Guidelines for Implementers

  1. We use the terms MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY as defined by IETF RFC 2119

  2. We use the term "the server" when discussing the specific behaviour required of a conforming AMQP server

  3. We use the term "the client" when discussing the specific behaviour required of a conforming AMQP client

  4. We use the term "the peer" to mean "the server or the client"

  5. All numeric values are decimal unless otherwise indicated

  6. Protocol constants are shown as upper-case names. AMQP implementations SHOULD use these names when defining and using constants in source code and documentation

  7. Property names, method arguments, and frame fields are shown as lower-case names. AMQP implementations SHOULD use these names consistently in source code and documentation.

  8. Names in AMQP are case-sensitive. For example, "amq.Direct" specifies a different exchange from "amq.direct".

§ 1.5.2 Version Numbering

The AMQP version is expressed using two numbers – the major number and the minor number. By convention, the version is expressed as the major, number followed by a dash, followed by the minor number. (For example, 1-3 is major = 1, minor = 3.)

  1. Major and minor numbers may take any value between 0 and 255 inclusive.

  2. Minor numbers are incremented with the major version remaining unchanged. When the AMQP working group decides that a major version is appropriate, the major number is incremented, and the minor number is reset to 0. Thus, a possible sequence could be 1-2, 1-3, 1-4, 2-0, 2-1...

  3. Once the protocol reaches production (major >= 1), minor numbers greater than 9 would be strongly discouraged. However, prior to production (versions 0-x), this may occur owing to the rapid and frequent revisions of the protocol.

  4. Once the protocol reaches production (major >=1), backwards compatibility between minor versions of the same major version must be guaranteed by implementers. Conversely, backwards compatibility between minor versions prior to production is neither guaranteed nor expected.

  5. Major versions numbers of 99 and above are reserved for internal testing and development purposes.

  6. The rule which divides the major byte in the AMQP header by 10 to achieve the major number used in version 0-8 of this protocol is discontinued. The major version is stored directly in the major byte and the minor number directly in the minor byte. (See {{CHAPTERNUMBER}} Protocol Header on page {{PAGENUMBER}} for details.)

§ 1.5.3 Technical Terminology

These terms have special significance within the context of this document:

  1. AMQP Command Architecture: An encoded wire-level protocol command which executes actions on the state of the AMQP Model Architecture.

  2. AMQP Model Architecture: A logical framework representing the key entities and semantics which must be made available by an AMQP compliant server implementation, such that the server can be meaningfully manipulated by AMQP Commands sent from a client in order to achieve the semantics defined in this specification.

  3. Connection: A network connection, e.g. a TCP/IP socket connection

  4. TODO: need to update based on 74

    Channel: A bi-directional stream of communications between two AMQP peers. Channels are multiplexed so that a single network connection can carry multiple channels

  5. Client: The initiator of an AMQP connection or channel. AMQP is not symmetrical. Clients produce and consume messages while servers queue and route messages

  6. Server: The process that accepts client connections and implements the AMQP message queueing and routing functions. Also known as "broker"

  7. Peer: Either party in an AMQP connection. An AMQP connection involves exactly two peers (one is the client, one is the server)

  8. Frame: A formally-defined package of connection data. Frames are always written and read contiguously - as a single unit - on the connection

  9. Protocol Class: A collection of AMQP commands (also known as Methods) that deal with a specific type of functionality

  10. Method: A specific type of AMQP command frame that passes instructions from one peer to the other

  11. Content: Application data passed from client to server and from server to client. AMQP content can be structured into multiple parts. The term is synonymous with "message"

  12. Content Header: A specific type of frame that describes a content's properties

  13. Content Body: A specific type of frame that contains raw application data. Content body frames are entirely opaque - the server does not examine or modify these in any way

  14. Message: Synonymous with "content"

  15. Exchange: The entity within the server which receives messages from producer applications and optionally routes these to message queues within the server

  16. Exchange Type: The algorithm and implementation of a particular model of exchange. In contrast to the "exchange instance", which is the entity that receives and routes messages within the server

  17. Message queue: A named entity that holds messages and forwards them to consumer applications.

  18. Binding: An entity that creates a relationship between a message queue and an exchange

  19. Routing key: A virtual address that an exchange may use to decide how to route a specific message

  20. Durable: A server resource that survives a server restart

  21. Transient: A server resource that is wiped or reset after a server restart

  22. Persistent: A message that the server holds on reliable disk storage and MUST NOT lose after a server restart

  23. Non-persistent: A message that the server holds in memory and MAY lose after a server restart

  24. Consumer: A client application that requests messages from a message queue

  25. Producer: A client application that publishes messages to an exchange

  26. Virtual host: A collection of exchanges, message queues and associated objects. Virtual hosts are independent server domains that share a common authentication and encryption environment. The client application chooses a virtual host after logging in to the server

  27. Realm: A set of server resources (exchanges and message queues) covered by a single security policy and access control. Applications ask for access rights for specific realms, rather than for specific resources

  28. Ticket: A token that a server provides to a client, for access to a specific realm

  29. Streaming: The process by which the server will send messages to the client at a pre-arranged rate

  30. Staging: The process by which a peer will transfer a large message to a temporary holding area before formally handing it over to the recipient. This is how AMQP implements re-startable file transfers

  31. Out-of-band transport: The technique by which data is carried outside the network connection. For example, one might send data across TCP/IP and then switch to using shared memory if one is talking to a peer on the same system

  32. Zero copy: The technique of transferring data without copying it to or from intermediate buffers. Zero copy requires that the protocol allows the out-of-band transfer of data as opaque blocks, as AMQP does

  33. Assertion: A condition that must be true for processing to continue

  34. Exception: A failed assertion, handled by closing either the Channel or the Connection

These terms have no special significance within the context of AMQP:

  1. Topic: Usually a means of distributing messages; AMQP implements topics using one or more types of exchange

  2. Subscription: Usually a request to receive data from topics; AMQP implements subscriptions as message queues and bindings

  3. Service: Usually synonymous with server. The AMQP standard uses "server" to conform with IETF standard nomenclature and to clarify the roles of each party in the protocol (both sides may be AMQP services)

  4. Broker: synonymous with server. The AMQP standard uses the terms "client" and "server" to conform with IETF standard nomenclature.

  5. Router: Sometimes used to describe the actions of an exchange. However exchanges can do more than message routing (they can also act as message end-points), and the term "router" has special significance in the network domain, so AMQP avoids using it.

TODO: merge the following definitions
TODO: factor definitions into model definitions and protocol definitions
TODO: define segments, subchannels, session layer, network mapping layer, DLQs, head-of-line blocking, framing version
  1. Session: Sessions are the central repository for all state that makes up the relationship between two AMQP peers (usually client and broker). A session can be seen as:

  2. Channel: A transport-level notion; a stream of transport-level frames that can be associated with a session.

  3. Attachment: The relationship between a transport-level stream of frames, such as a channel carried over a TCP connection, and a Session.

  4. Ack struct: Information, held with a session's state, about which frames have been processed by the session layer in each direction within a session's peer-to-peer link; used to translate idempotence at the session level into exactly-once delivery at the functional level.

  5. Frame: Smallest unit of AMQP information; transported through the network protocol mapping layer.

  6. Frameset: A collection of frames that together make up a command, a message transfer, or a control message. A logical unit of work that can be interpreted by layers above the session layer.

  7. Segment Type: Indicates the physical format and purpose of a segment.

  8. Control: A frameset directed at a specific AMQP layer below the model layers. L1 controls are directed at the network protocol mapping layer, and L2 controls are directed at the session layer. See AMQP:TSP:Layering#Layering_of_Control and AMQP:TSP:Layering#Communication_between_peers_at_each_layer.

  9. Execution Layer: Provides synchronization and correlation of commands. This is where processed level acknowledgment occurs. Below the execution layer is the transport layer. The transport layer must provide scoped (timeout based) stream oriented reliability, e.g. TCP or SCTP. The layer above defines the detailed semantics of each command.

  10. Synchronization: In this context the term synchronization refers to synchronizing world views. This does not imply anything at all about waiting for a peer to peer round trip to occur.

  11. World View: In addition to its own internal state each peer in an AMQP interaction may have an internal representation of the state of one or more of its Partner's. This is referred to as the Peer's World View.

  12. Correlation: Correlation is a mechanism used by a Peer to reference commands previously sent by its Partner within a given session.

  13. Command: The layer 3 (semantic layer) client server dialog is composed of atomic semantic units called commands. A command is the only indivisible semantic unit.

  14. Message: A message is user data formatted as a standard set of headers, an application defined set of headers, and an opaque body. A message is carried by one or more commands.

  15. Delivery Contract: The subset of publish arguments and message headers pertaining to the delivery of a single message. This includes delivery mode (durable, transient), ttl, immediate, exchange name, routing key, etc. These form a contract between the broker and the publisher. This contract is unique to a particular message.

  16. Peer: The term Peer refers to the process controlling either end of an AMQP interaction.

  17. Partner: The term Partner is used as a convenient shorthand for describing the "other" Peer when describing an interaction between two Peers. For example if we have defined Peer A and Peer B as opposite ends of a given interaction, then Peer B is Peer A's Partner and Peer A is Peer B's partner.

  18. Durable: Capable of surviving long-term power outages.

  19. Round Trip: The term round trip refers to the process of a peer sending a command to its partner and receiving confirmation that the command is complete. Round trips are necessary for synchronization of world views, however, it is not necessary for a client to wait and do nothing while a round trip occurs or only deal with a single round trip at a time.

  20. Round Trip Time (RTT): The term RTT refers to the time taken to complete a round trip. This is described with the following formula:

    RTT = 2*latency_network + latency_processing
    

    Note that RTT at the execution layer differs from RTT at the network layer. At the network layer the processing latency is zero resulting in an RTT of twice the network latency. At the execution layer the processing time becomes significant if, for example, processing the command requires sending data to disk. This would be the case with durable messages and the RTT would then include the Broker's disk latency.

§ 2 Model

§ 2.1 AMQP Model Architecture

This section explains the server semantics that must be standardised in order to guarantee interoperability between AMQP implementations.

§ 2.1.1 Main Entities

This diagram shows the overall AMQP Model:

                                 Server
                      +----------------------------+
                      |       Virtual host         |
                      |   +-------------------+    |
                      |   |     Exchange      |    |
    +-------------+   |   |     +-------+     |    |
    |  Publisher  | ----------> |       |     |    |
    | application |   |   |     +---+---+     |    |
    +-------------+   |   |         |         |    |
                      |   |      Message      |    |
                      |   |       Queue       |    |
    +-------------+   |   |     +-------+     |    |
    |  Consumer   | <---------- +-------+     |    |
    | application |   |   |     +-------+     |    |
    +-------------+   |   |     +-------+     |    |
                      |   +-------------------+    |
                      +----------------------------+

We can summarise what a middleware server is: it is a data server that accepts messages and does two main things with them, it routes them to different consumers depending on arbitrary criteria, and it buffers them in memory or on disk when consumers are not able to accept them fast enough.

In a pre-AMQP server these tasks are done by monolithic engines that implement specific types of routing and buffering. The AMQP Model takes the approach of smaller, modular pieces that can be combined in more diverse and robust ways. It starts by dividing these tasks into two distinct roles:

  1. The exchange, which accepts messages from producers and routes them message queues

  2. The message queue, which stores messages and forwards them to consumer applications

There is a clear interface between exchange and message queue, called a "binding", which we will come to later. The usefulness of the AMQP Model comes from three main features:

  1. The ability to create arbitrary exchange and message queue types (some are defined in the standard, but others can be added as server extensions)

  2. The ability to wire exchanges and message queues together to create any required message-processing system

  3. The ability to control this completely through the protocol

In fact, AMQP provides runtime-programmable semantics.

§ 2.1.1.1 The Message Queue

A message queue stores messages in memory or on disk, and delivers these in sequence to one or more consumer applications. Message queues are message storage and distribution entities. Each message queue is entirely independent and is a reasonably clever object.

A message queue has various properties: private or shared, durable or temporary, client-named or server-named, etc. By selecting the desired properties we can use a message queue to implement conventional middleware entities such as:

  1. A standard store-and-forward queue, which holds messages and distributes these between consumers on a round-robin basis. Store and forward queues are typically durable and shared between multiple consumers

  2. A temporary reply queue, which holds messages and forwards these to a single consumer. Reply queues are typically temporary, server-named, and private to one consumer

  3. A "pub-sub" subscription queue, which holds messages collected from various "subscribed" sources, and forwards these to a single consumer.

Subscription queues are typically temporary, server-named, and private to one consumer.

These categories are not formally defined in AMQP: they are examples of how message queues can be used. It is trivial to create new entities such as durable, shared subscription queues.

§ 2.1.1.2 The Exchange

An exchange accepts messages from a producer application and routes these to message queues according to pre-arranged criteria. These criteria are called "bindings". Exchanges are matching and routing engines. That is, they inspect messages and using their binding tables, decide how to forward these messages to message queues or other exchanges. Exchanges never store messages.

The term "exchange" is used to mean both a class of algorithm, and the instances of such an algorithm. More properly, we speak of the "exchange type" and the "exchange instance".

AMQP defines a number of standard exchange types, which cover the fundamental types of routing needed to do common message delivery. AMQP servers will provide default instances of these exchanges. Applications that use AMQP can additionally create their own exchange instances. Exchange types are named so that applications which create their own exchanges can tell the server what exchange type to use. Exchange instances are also named so that applications can specify how to bind queues and publish messages.

Exchanges can do more than route messages. They can act as intelligent agents that work from within the server, accepting messages and producing messages as needed. The exchange concept is intended to define a model for adding extensibility to AMQP servers in a reasonably standard way, since extensibility has some impact on interoperability.

§ 2.1.1.3 The Routing Key

In the general case an exchange examines a message's properties, its header fields, and its body content, and using this and possibly data from other sources, decides how to route the message.

In the majority of simple cases the exchange examines a single key field, which we call the "routing key". The routing key is a virtual address that the exchange may use to decide how to route the message.

For point-to-point routing, the routing key is the name of a message queue.

For topic pub-sub routing, the routing key is the topic hierarchy value.

In more complex cases the routing key may be combined with routing on message header fields and/or its content.

§ 2.1.1.4 Analogy to Email

If we make an analogy with an email system we see that the AMQP concepts are not radical:

  1. an AMQP message is analogous to an email message

  2. a message queue is like a mailbox

  3. a consumer is like a mail client that fetches and deletes email

  4. a exchange is like a MTA (mail transfer agent) that inspects email and decides, on the basis of routing keys and tables, how to send the email to one or more mailboxes

  5. a routing key corresponds to an email To: or Cc: or Bcc: address, without the server information (routing is entirely internal to an AMQP server)

  6. each exchange instance is like a separate MTA process, handling some email sub-domain, or particular type of email traffic

  7. a binding is like an entry in a MTA routing table.

The power of AMQP comes from our ability to create queues (mailboxes), exchanges (MTA processes), and bindings (routing entries), at runtime, and to chain these together in ways that go far beyond a simple mapping from "to" address to mailbox name.

We should not take the email-AMQP analogy too far: there are fundamental differences. The challenge in AMQP is to route and store messages within a server, or SMTPFootnote:

SMTP is the Simple Mail Transport Protocol as defined by the IETF.

parlance calls them "autonomous systems". By contrast, the challenge in email is to route messages between autonomous systems.

Routing within a server and between servers are distinct problems and have distinct solutions, if only for banal reasons such as maintaining transparent performance.

To route between AMQP servers owned by different entities, one sets up explicit bridges, where one AMQP server acts and the client of another server for the purpose of transferring messages between those separate entities. This way of working tends to suit the types of businesses where AMQP is expected to be used, because these bridges are likely to be underpinned by business processes, contractual obligations and security concerns. This model also makes AMQP 'spam' more difficult.

§ 2.1.2 Message Flow

This diagram shows the flow of messages through the AMQP Model server:

    +-------------+                    +-------+
    |  Publisher  | -----------------> |Message|
    | application |                    +---+---+
    +-------------+                        |
                                           |
                                      +---------+
                                      |Exchange |
                                      +----+----+
                                           |
                              +------------+------------+
                              |            |            |
                           Message      Message      Message
                            Queue        Queue        Queue
    +-------------+       +-------+    +-------+    +-------+
    |  Consumer   |       +-------+    +-------+    +-------+
    | application | <---- |Message|    +-------+    +-------+
    +-------------+       +-------+    +-------+    +-------+

§ 2.1.2.1 Message Life-cycle

An AMQP message consists of a set of properties plus opaque content.

A new "message" is created by a producer application using an AMQP client API. The producer places "content" in the message and perhaps sets some message "properties". The producer labels the message with "routing information", which is superficially similar to an address, but almost any scheme can be created. The producer then sends the message to an "exchange" on the server.

When the message arrives at the server, the exchange (usually) routes the message to a set of message "queues" which also exist on the server. If the message is unroutable, the exchange may drop it silently or return it to the producer. The producer chooses how unroutable messages are treated.

A single message can exist on many message queues. The server can handle this in different ways, by copying the message, by using reference counting, etc. This does not affect interoperability. However, when a message is routed to multiple message queues, it is identical on each message queue. There is no unique identifier that distinguishes the various copies.

When a message arrives in a message queue, the message queue tries immediately to pass it to a consumer application via AMQP. If this is not possible, the message queue stores the message (in memory or on disk as requested by the producer) and waits for a consumer to be ready. If there are no consumers, the message queue may return the message to the producer via AMQP (again, if the producer asked for this).

When the message queue can deliver the message to a consumer, it removes the message from its internal buffers. This can happen immediately, or after the consumer has acknowledged that it has successfully processed the message. The consumer chooses how and when messages are "acknowledged". The consumer can also reject a message (a negative acknowledgement).

Producer messages and consumer acknowledgements are grouped into "transactions". When an application plays both roles, which is often, it does a mix of work: sending messages and sending acknowledgements, and then committing or rolling back the transaction.

Message deliveries from the server to the consumer are not transacted; it is sufficient to transact the acknowledgements to these messages

§ 2.1.2.2 What The Producer Sees

By analogy with the email system, we can see that a producer does not send messages directly to a message queue. Allowing this would break the abstraction in the AMQP Model. It would be like allowing email to bypass the MTA's routing tables and arrive directly in a mailbox. This would make it impossible to insert intermediate filtering and processing, spam detection, for instance.

The AMQP Model uses the same principle as an email system: all messages are sent to a single point, the exchange or MTA, which inspects the messages based on rules and information that are hidden from the sender, and routes them to drop-off points that are also hidden from the sender.

§ 2.1.2.3 What The Consumer Sees

Our analogy with email starts to break down when we look at consumers. Email clients are passive - they can read their mailboxes, but they do not have any influence on how these mailboxes are filled. An AMQP consumer can also be passive, just like email clients. That is, we can write an application that expects a particular message queue to be ready and bound, and which will simply process messages off that message queue.

However, we also allow AMQP client applications to:

  1. create or destroy message queues

  2. define the way these message queues are filled, by making bindings

  3. select different exchanges which can completely change the routing semantics

This is like having an email system where one can, via the protocol:

  1. create a new mailbox

  2. tell the MTA that all messages with a specific header field should be copied into this mailbox

  3. completely change how the mail system interprets addresses and other message headers

We see that AMQP is more like a language for wiring pieces together than a system. This is part of our objective, to make the server behaviour programmable via the protocol.

§ 2.1.2.4 Automatic Mode

Most integration architectures do not need this level of sophistication. Like the amateur photographer, a majority of AMQP users need a "point and shoot" mode. AMQP provides this through the use of two simplifying concepts:

  1. a default exchange for message producers

  2. a default binding for message queues that selects messages based on a match between routing key and message queue name

In effect, the default binding lets a producer send messages directly to a message queue, given suitable authority – it emulates the simplest "send to destination" addressing scheme people have come to expect of traditional middleware.

The default binding does not prevent the message queue from being used in more sophisticated ways. It does, however, let one use AMQP without needing to understand how exchanges and bindings work.

NOTE: It is only possible to use the default exchange and bindings through publish methods (such a method.transfer) in which a blank exchange name is used. It is not possible to directly access, create or delete these exchanges or bindings.

§ 2.1.3 Exchanges

§ 2.1.3.1 Types of Exchange

Each exchange type implements a specific routing algorithm. There are a number of standard exchange types, explained in the "Functional Specifications" chapter, but there are two that are particularly important:

  1. the "direct" exchange type, which routes on a routing key

  2. the "topic" exchange type, which routes on a routing pattern

Note that:

  1. the default exchange is a "direct" exchange

  2. the server will create a "direct" and a "topic" exchange at start-up with well-known names and client applications may depend on this

§ 2.1.3.2 Exchange Life-cycle

Each AMQP server pre-creates a number of exchanges (more pedantically, "exchange instances"). These exchanges exist when the server starts and cannot be destroyed.

AMQP applications can also create their own exchanges. AMQP does not use a "create" method as such, it uses a "declare" method which means, "create if not present, otherwise continue". It is plausible that applications will create exchanges for private use and destroy them when their work is finished. AMQP provides a method to destroy exchanges but in general applications do not do this.

In our examples in this chapter we will assume that the exchanges are all created by the server at start-up. We will not show the application declaring its exchanges.

§ 2.1.4 Message Queues

§ 2.1.4.1 Message Queue Properties

When a client application creates a message queue, it can select some important properties:

  1. name - if left unspecified, the server chooses a name and provides this to the client. Generally, when applications share a message queue they agree on a message queue name beforehand, and when an application needs a message queue for its own purposes, it lets the server provide a name

  2. durable - if specified, the message queue remains present and active when the server restarts. It may lose non-persistent messages if the server restarts

  3. auto-delete - if specified, the server will delete the message queue when all clients have finished using it, or shortly thereafter.

§ 2.1.4.2 Queue Life-cycles

There are two main message queue life-cycles:

  1. Durable message queues that are shared by many consumers and have an independent existence - i.e. they will continue to exist and collect messages whether or not there are consumers to receive them

  2. Temporary message queues that are private to one consumer and are tied to that consumer. When the consumer disconnects, the message queue is deleted.

There are some variations on these, such as shared message queues that are deleted when the last of many consumers disconnects.

TODO: revisit this diagram, it has a tie fighter in it

This diagram shows the way temporary message queues are created and deleted:

                               Message
                                Queue
                              +-------+
                    Declare   +-------+  Message queue is created
                    --------> +-------+
    +-------------+           +-------+
    |  Consumer   | Consume
    | application | -------->
    +-------------+           \       /
                    Cancel    +\\----/*
                    --------> +--\\//-+  Message queue is deleted
                              +--//\\-+
                              +//----\*
                              /        \

§ 2.1.5 Bindings

A binding is the relationship between an exchange and a message queue that tells the exchange how to route messages. Bindings are constructed from commands from the client application (the one owning and using the message queue) to an exchange. We can express a binding command in pseudo-code as follows:

Queue.Bind <queue> TO <exchange> WHERE <condition>

Let's look at three typical use cases: shared queues, private reply queues, and pub-sub subscriptions.

§ 2.1.5.1 Constructing a Shared Queue

Shared queues are the classic middleware "point-to-point queue". In AMQP we can use the default exchange and default binding. Let's assume our message queue is called "app.svc01". Here is the pseudo-code for creating the shared queue:

Queue.Declare
    queue=app.svc01
    exclusive=FALSE

We may have many consumers on this shared queue. To consume from the shared queue, each consumer does this:

Basic.Consume
    queue=app.svc01

To publish to the shared queue, each producer sends a message to the default exchange:

Basic.Publish
    routing_key=app.svc01

§ 2.1.5.2 Constructing a Reply Queue

Reply queues are usually temporary, with server-assigned names. They are also usually private, i.e. read by a single consumer. Apart from these particularities, reply queues use the same matching criteria as standard queues, so we can also use default exchange.

Here is the pseudo-code for creating a reply queue, where S: indicates a server reply:

Queue.Declare
    queue=<empty>
    exclusive=TRUE
    auto_delete=TRUE
S:Queue.Create-Ok
    queue=tmp.1

To publish to the reply queue, a producer sends a message to the default exchange:

Basic.Publish
    routing_key=tmp.1

One of the standard message properties is Reply-To, which is designed specifically for carrying the name of reply queues.

§ 2.1.5.3 Constructing a Pub-Sub Subscription Queue

In classic middleware the term "subscription" is vague and refers to at least two different concepts: the set of criteria that match messages and the temporary queue that holds matched messages. AMQP separates the work into into bindings and message queues. There is no AMQP entity called "subscription".

Let us agree that a pub-sub subscription:

  1. holds messages for a single consumer (or in some cases for multiple consumers)

  2. collects messages from multiple sources, through a set of bindings that match topics, message fields, or content in different ways.

The key difference between a subscription queue and a named or reply queue is that the subscription queue name is irrelevant for the purposes of routing, and routing is done on abstracted matching criteria rather than a 1-to-1 matching of the routing key field.

Let's take the common pub-sub model of "topic trees" and implement this. We need an exchange type capable of matching on a topic tree. In AMQP this is the "topic" exchange type. The topic exchange matches wild-cards like "STOCK.USD.*" against routing key values like "STOCK.USD.NYSE".

We cannot use the default exchange or binding because these do not do topic-style routing. So we have to create a binding explicitly. Here is the pseudo-code for creating and binding the pub-sub subscription queue:

Queue.Declare
    queue=<empty>
    auto_delete=TRUE
S:Queue.Declare-Ok
    queue=tmp.2
Queue.Bind
    queue=tmp.2
    TO exchange=amq.topic
    WHERE routing_key=STOCK.USD.*

To consume from the subscription queue, the consumer does this:

    Basic.Consume
        queue=tmp.2

When publishing a message, the producer does something like this:

Basic.Publish
    exchange=amq.topic
    routing_key=STOCK.USD.IBM

The topic exchange processes the incoming routing key ("STOCK.USD.IBM") with its binding table, and finds one match, for tmp.2. It then routes the message to that subscription queue.

§ 2.1.6 Interface to L4 Sessions

TODO: describe L4 Sessions from the model's perspective

§ 2.2 Functional Specification

§ 2.2.1 Messages and Content

A message is the atomic unit of processing of the middleware routing and queuing system. Messages carry a content, which consists of a content header, holding a set of properties, and a content body, holding an opaque block of binary data. Contents can themselves contain child contents, to any level of complexity.

A message can correspond to many different application entities:

  1. An application-level message

  2. A file to transfer

  3. One frame of a data stream

  4. etc.

AMQP defines a set of "content classes", each implementing a specific content syntax (the set of content header properties) and semantics (the methods that are available to manipulate messages of that content class).

Messages may be persistent, according to the semantics of each class. A persistent message is held securely on disk and guaranteed to be delivered even if there is a serious network failure, server crash, overflow etc.

Messages may have a priority level, according to the semantics of each class. A high priority message is sent ahead of lower priority messages waiting in the same message queue. When messages must be discarded in order to maintain a specific service quality level the server will first discard low-priority messages.

The server MUST NOT modify message content bodies that it receives and passes to consumer applications. The server MAY add information to content headers but it MUST NOT remove or modify existing information.

§ 2.2.1.1 Message Transport

TODO: move somewhere into model section
§ 2.2.1.1.1 Quality of Service

The quality of service controls how fast messages are sent. The quality of service depends on the type of content being distributed. For basic messaging, for file transfer, and for streaming, we define different quality of service semantics.

In general the quality of service uses the concept of "pre-fetch" to specify how many messages or how many octets of data will be sent before the client acknowledges a message. The goal is to send message data in advance, to reduce latency.

§ 2.2.1.1.2 Acknowledgements

An acknowledgement is a formal signal from the client application to a message queue that it has successfully processed a message. There are two possible acknowledgement models:

  1. Automatic, in which the server removes a content from a message queue as soon as it delivers it to an application (via the Deliver or Get-Ok methods).

  2. Explicit, in which the client application must send an Ack method for each message, or batch of messages, that it has processed.

The client layers can themselves implement explicit acknowledgements in different ways, e.g. as soon as a message is received, or when the application indicates that it has processed it. These differences do not affect AMQP or interoperability.

§ 2.2.1.1.3 Flow Control

Flow control is an emergency procedure used to halt the flow of messages from a peer. It works in the same way between client and server and is implemented by the Channel.Flow command. Flow control is the only mechanism that can stop an over-producing publisher. A consumer can use the more elegant mechanism of pre-fetch windowing, if it uses message acknowledgements (which usually means using transactions).

§ 2.2.2 Virtual Hosts

A Virtual HostFootnote:

The term Virtual Host is taken from the use popularised by the Apache HTTP server. Apache Virtual Hosts enable Internet Service providers to provide bulk hosting from one shared server infrastructure. We hope that the inclusion of this capability within AMQP opens up similar opportunities to larger organisations.

is a data partition within the server, it is an administrative convenience which will prove useful to those wishing to provide AMQP as a service on a shared infrastructure.

A virtual host comprises its own name space, a set of exchanges, message queues, and all associated objects. Each connection MUST BE associated with a single virtual host.

The client selects the virtual host in the Connection.Open method, after authentication. This implies that the authentication scheme of the server is shared between all virtual hosts on that server. However, the authorization scheme used MAY be unique to each virtual host. This is intended to be useful for shared hosting infrastructures. Administrators who need different authentication schemes for each virtual host should use separate servers.

All channels within the connection work with the same virtual host. There is no way to communicate with a different virtual host on the same connection, nor is there any way to switch to a different virtual host without tearing down the connection and beginning afresh.

The protocol offers no mechanisms for creating or configuring virtual hosts - this is done in an undefined manner within the server and is entirely implementation-dependent.

§ 2.2.3 Exchanges

An exchange is a message routing agent within a virtual host. An exchange instance (which we commonly call "an exchange") accepts messages and routing information - principally a routing key - and either passes the messages to message queues, or to internal services. Exchanges are named on a per-virtual host basis.

Exchange names must consist of between 1 and 127 characters, and must be limited to letters (both lower- and upper-case), digits (0-9) and the underscore character ('_').

Applications can freely create, share, use, and destroy exchange instances, within the limits of their authority.

Exchanges may be durable, temporary, or auto-deleted. Durable exchanges last until they are deleted. Temporary exchanges last until the server shuts-down. Auto-deleted exchanges last until they are no longer used.

The server provides a specific set of exchange types. Each exchange type implements a specific matching and algorithm, as defined in the next section. AMQP mandates a small number of exchange types, and recommends some more. Further, each server implementation may add its own exchange types.

An exchange can route a single message to many message queues in parallel. This creates multiple instances of the message that are consumed independently.

§ 2.2.3.1 The Direct Exchange Type

The direct exchange type works as follows:

  1. A message queue binds to the exchange using a routing key, K.

  2. A publisher sends the exchange a message with the routing key R.

  3. The message is passed to the message queue if K = R.

The server MUST implement the direct exchange type and MUST pre-declare within each virtual host at least two direct exchanges: one named amq.direct, and one with no public name that serves as the default exchange for Publish methods.

Note that message queues can bind using any valid routing key value, but most often message queues will bind using their own name as routing key.

In particular, all message queues MUST BE automatically bound to the nameless exchange using the message queue's name as routing key.

§ 2.2.3.2 The Fanout Exchange Type

The fanout exchange type works as follows:

  1. A message queue binds to the exchange with no arguments.

  2. A publisher sends the exchange a message.

  3. The message is passed to the message queue unconditionally.

The fanout exchange is trivial to design and implement. This exchange type, and a pre-declared exchange called amq.fanout, are mandatory.

§ 2.2.3.3 The Topic Exchange Type

The topic exchange type works as follows:

  1. A message queue binds to the exchange using a routing pattern, P.

  2. A publisher sends the exchange a message with the routing key R.

  3. The message is passed to the message queue if R matches P.

The routing key used for a topic exchange MUST consist of zero or more words delimited by dots. Each word may contain the letters A-Z and a-z and digits 0-9.

The routing pattern follows the same rules as the routing key with the addition that * matches a single word, and # matches zero or more words. Thus the routing pattern *.stock.# matches the routing keys usd.stock and eur.stock.db but not stock.nasdaq.

One suggested design for the topic exchange is to hold the set of all known routing keys, and update this when publishers use new routing keys. It is possible to determine all bindings for a given routing key, and so to rapidly find the message queues for a message. This exchange type is optional.

The server SHOULD implement the topic exchange type and in that case, the server MUST pre-declare within each virtual host at least one topic exchange, named amq.topic.

§ 2.2.3.4 The Headers Exchange Type

The headers exchange type works as follows:

1. A message queue is bound to the exchange with a table of arguments containing the headers to be matched for that binding and optionally the values they should hold. The routing key is not used.

2. A publisher sends a message to the exchange where the 'headers' property contains a table of names and values.

3. The message is passed to the queue if the headers property matches the arguments with which the queue was bound.

The matching algorithm is controlled by a special bind argument passed as a name value pair in the arguments table. The name of this argument is 'x-match'. It can take one of two values, dictating how the rest of the name value pairs in the table are treated during matching:

(i) 'all' implies that all the other pairs must match the headers property of a message for that message to be routed (i.e. and AND match)

(ii) 'any' implies that the message should be routed if any of the fields in the headers property match one of the fields in the arguments table (i.e. an OR match)

A field in the bind arguments matches a field in the message if either the field in the bind arguments has no value and a field of the same name is present in the message headers or if the field in the bind arguments has a value and a field of the same name exists in the message headers and has that same value.

Any field starting with 'x-' other than 'x-match' is reserved for future use and will be ignored.

The server SHOULD implement the headers exchange type and in that case, the server MUST pre-declare within each virtual host at least one headers exchange, named amq.match.

§ 2.2.3.5 The System Exchange Type

The system exchange type works as follows:

  1. A publisher sends the exchange a message with the routing key S.

  2. The system exchange passes this to a system service S.

System services starting with "amq." are reserved for AMQP usage. All other names may be used freely on by server implementations. This exchange type is optional.

§ 2.2.3.6 Implementation-defined Exchange Types

All non-normative exchange types MUST be named starting with "x-". Exchange types that do not start with "x-" are reserved for future use in the AMQP standard.

§ 2.2.4 Message Queues

A message queue is a named FIFO buffer that holds message on behalf of a set of consumer applications. Applications can freely create, share, use, and destroy message queues, within the limits of their authority.

Note that in the presence of multiple readers from a queue, or client transactions, or use of priority fields, or use of message selectors, or implementation-specific delivery optimisations the queue MAY NOT exhibit true FIFO characteristics. The only way to guarantee FIFO is to have just one consumer connected to a queue. The queue may be described as "weak-FIFO" in these cases.

Message queues may be durable, temporary, or auto-deleted. Temporary message queues last until the server shuts-down. Auto-deleted message queues last until they are no longer used. Any queue may be explicitly deleted if the user (client) has the appropriate permissions.

Message queues hold their messages in memory, on disk, or some combination of these. Message queues are named on a per-virtual host basis.

Queue names must consist of between 1 and 255 characters. The first character must be limited to letters (both lower- and upper-case), digits (0-9) and the underscore character ('_'); all those following must be legal UTF-8 characters.

Message queues hold messages and distribute them between one or more consumer clients. A message routed to a message queue is never sent to more than one client unless it is is being resent after a failure or rejection.

A single message queue can hold different types of content at the same time and independently. That is, if Basic and File contents are sent to the same message queue, these will be delivered to consuming applications independently as requested.

§ 2.2.5 Bindings

A binding is a relationship between a message queue and an exchange. The binding specifies routing arguments that tell the exchange which messages the queue should get.

Applications create and destroy bindings as needed to drive the flow of messages into their message queues. The lifespan of bindings depend on the message queues they are defined for - when a message queue is destroyed, its bindings are also destroyed.

The specific semantics of the Queue.Bind method depends on the exchange type.

§ 2.2.6 Consumers

We use the term "consumer" to mean both the client application and the entity that controls how a specific client application receives messages off a message queue. When the client "starts a consumer" it creates a consumer entity in the server. When the client "cancels a consumer" it destroys a consumer entity in the server.

Consumers belong to a single client channel and cause the message queue to send messages asynchronously to the client.

§ 2.2.7 Transactions

§ 2.2.7.1 Distributed Transactions

The distributed transaction classes provide support for the X-Open XA architecture.

The dtx-demarcation class is used to demarcate transaction boundaries on a given channel that is subsequently used to perform AMQP native transactional work (produce publish messages). Transaction coordination and recovery operations are provided by the dtx-coordination class.

Both OMG OTS and JTS/JTA models rely on "Resource Manager Client", RM Client, instances (object identified by Rmids through the xa_switch in c/c++or XAResource instances in Java) that implement the XA interface for the underlying resource to participate with a global transaction.

As depicted on the following figure, a Transaction Manager uses RM Client XA interface to demarcate transaction boundaries and coordinate transaction outcomes. RM Clients use the dtx-demarcation class to associate transactional work with a transactional channel. The transactional channel is exposed to the application driving the transaction. The application can then use the transactional channel to transactionally produce and consume messages. RM clients use dtx-coordination to propagate transaction outcomes and recovery operations to the AMQP broker. A second coordination channel can be used for that purpose.

                        +---+---------------+                +--------+
                        |   |  prepare/commit/rollback  +----|        |
+-------------+    XA   | X |===============|==========>| CC |        |
|     TM      |<========| A |               |           +----|        |
+-------------+         |   |===========+   |   Coordination |        |
       ^                +---+ start/end |   |        Channel | AMQP   |
       | start/         |               |   |                | Broker |
       | commit/        +---+ RM Client |   |  Transactional |        |
       | rollback       | A |           |   |        Channel |        |
+-------------+         | M |           |   |           +----|        |
| Application |<========| Q |===========+===|==========>| TC |        |
+-------------+ produce | P |               |           +----|        |
                consume +---+---------------+                +--------+

§ 2.2.7.2 Distributed Transaction Use Cases

The following diagram illustrates a messaging scenario where an application "Application" transactionally consumes a message from a queue Q1 (using transaction T1 achieved through the transaction manger TM). Based on the consumed message, the application updates a database table Tb using DBMS and produces a message on queue Q2 on behalf transaction T1.

Appl.    TM         DBMS_RM_Client  AMQP_RM_Client                  AMQP_Broker

 |        |                |            |                                |
 | begin  |                |            |                                |
 +------->+  xa_start(T1)  |            |                                |
 |        +--------------->+            |                                |
 |        |        xa_start(T1)         |                                |
 |        +---------------------------->+     dtx-demarcation.select     |
 |        |                |            +------------------------------->+  \
 |        |                |            |  dtx-demarcation.start(xid1)   |   |
 |        |                |            +------------------------------->+   |
 |      consume a message from Q1       |                                |   | T
 +------------------------------------->+      message.consume(Q1)       |   | r
 |        |                |            +------------------------------->+   | a
 |        |                |            |     acknowledge message M      |   | n
 |        |                |            +------------------------------->+   | s
 |    update a table       |            |                                |   | a C
 +------------------------>+            |                                |   | c h
 |       produce a message on Q2        |                                |   | t .
 +------------------------------------->+      message.transfer(Q2)      |   | i
 |        |                |            +------------------------------->+   | o
 | commit |                |            |                                |   | n
 +------->+                |            |                                |   | a
 |        |   xa_end(T1)   |            |                                |   | l
 |        +--------------->+            |                                |   |
 |        |           xa_end(T1)        |                                |   |
 |        +---------------------------->+     dtx-demarcation.start      |   |
 |        |                |            +------------------------------->+  /
 |        | xa_prepare(T1) |            |                                |
 |        +--------------->+            |                                |     C
 |        |       xa_prepare(T1)        |                                |     o
 |        +---------------------------->+ dtx-coordination.prepare(xid1) |  \  o
 |        |                |            +------------------------------->+   | r
 |        | xa_commit(T1)  |            |                                |   | d
 |        +--------------->+            |                                |   | i C
 |        |       xa_commit(T1)         |                                |   | n h
 |        +---------------------------->+ dtx-coordination.commit(xid1)  |   | a .
 |        |                |            +------------------------------->+  /  t
 |        |                |            |                                |     i
                                                                               o
\_______________________________________/                                      n
            Thread of control

§ 2.2.8 Model Interface to L4 Session

TODO: edit into something reasonable

The logical model of a broker. Queues, exchanges, bindings, routing semantics, DLQs, etc. This layer defines how the remote APIs interact, e.g. when an exchange is configured via the exchange commands this becomes an available destination for the message transfer command.

§ 3 L4 Session

§ 3.1 AMQP Layering

TODO: Consistently use layer names instead of numbers.
       +------------------------------------------------------------------------------+
L4     |                 model (queues, exchanges, messages, transactions, ...)       |
       +------------------------------------------------------------------------------+
L3     |                 execution (AMQP-61)                                          |
       +------------------------------------------------------------------------------+

       +------------------------------------------------------------------------------+
L2.4   |                 stateful interceptors                                        |
L2.3   |                 frameset sequencing                                          |
L2.2   |                 frameset (dis)assembly                                       |
L2.1c  |                 "subchannel" demultiplex (v. AMQP-104)                       |
L2.1b ?|                 frame flow control                                           |
L2.1   |                 replication & recovery (AMQP-65)                             |
L2.0  ?|                 stateless interceptors                                       |
       +------------------------------------------------------------------------------+

       +-----------------------------------------+     +------------------------------+
L1b.2  | (de)multiplexing by channel             |     |  (de)multiplexing by stream  |
L1b.1  | stateless interceptors                  |     |  stateless interceptors      |
L1a    | framing, heartbeating, integrity check  |     |  framing                     |
       +-----------------------------------------+     +------------------------------+

       +-----------------------------------------+     +------------------------------+
(L0)   | TCP                                     |     |  SCTP                        |
       +-----------------------------------------+     +------------------------------+
  
Notes and bugs:

§ 3.1.1 Layering of Control

Illustration of control signals being fractionated out of the frame refinery stack:

       +-------------------------------+
L4     | model                         |
       +-------------------------------+
                      /|\
                       | commands
                       |
       +-------------------------------+
L3     | execution (AMQP-61)           |   -----> L3 controls??
       +-------------------------------+
                      /|\
                       | framesets
                       |
       +-------------------------------+
L2     | session                       |   -----> L2 control frames
       +-------------------------------+
             /|\            /|\
              | frames       | frames
              |              |
       +-------------+  +--------------+
L1     | TCP mapping |  | SCTP mapping |   -----> L1 control frames
       +-------------+  +--------------+
             /|\            /|\
              | bytes        | packets
              |              |
L0     -=-=-=-= packets/bytes =-=-=-=-=-
  
Some examples here would be good - e.g. "L1 control" could be TCP-heartbeat, or TCP-connection-tune; "L2 control" would be session.ack or session.hwm; L3 and L4 would need examples from AMQP-61 and from the regular stable of methods (e.g. queue.declare) respectively.

§ 3.1.2 Communication between peers at each layer

        +------------------+                            +------------------+
L4      |                  |       Semantic comms       |                  |
        |      model       |  <---------------------->  |      model       |
        +------------------+                            +------------------+
L3      |                  |                            |                  |
        |    execution     |  <---------------------->  |    execution     |
        +------------------+                            +------------------+
L2      |                  |     L2 control frames      |                  |
        |     session      |  <---------------------->  |     session      |
        +------------------+                            +------------------+
L1      |  network proto-  |     L1 control frames      |  network proto-  |
        |   col mapping    |  <---------------------->  |   col mapping    |
        +------------------+                            +------------------+
                /|\                                             /|\
                 |               Physical transport              |
L0               +-----------------------------------------------+
  

§ 3.2 AMQP Command Architecture

TODO: edit following paragraph for flow

Remote command APIs that expose the logical model over the network. These are grouped into independent subsets (classes or subprotocols). Clients can connect and use each subset without depending on another, e.g. a client can connect and configure exchanges without knowing anything about queues or messages. Similarly a client can connect and transfer messages without knowing anything about exchanges or queues.

TODO: the following updates (section numbers refer to the r173 odt from the tsp-f2f-20070604 branch)
2.2.4-2.2.12    postpone                mod     Move into doc tags for each class in the XML            tedious
2.2     3       TODO    mod+new Fill in general description of command architecture for 0-10            hard
2.2.9(.0)       postpone                mod     Keep this in the main doc, don't move it into the XML with its kids             easy
2.2.9(.0)       postpone                mod     Make it clear that this area of the spec is up for total revision before 1.0            easy
2.2.12.3        postpone                mod     Extract use cases to appendix? (see also next point)            easy
2.2.12(.0)      postpone                mod     DTX needs a separate doc besides the class definitions.         easy
2.3.2-2.3.3     postpone                mod     Keep only overview of data types; details to go into XML                tedious

This section explains how the application talks to the server.

§ 3.2.1 Protocol Commands (Classes & Methods)

Middleware is complex, and our challenge in designing the protocol structure was to tame that complexity. Our approach has been to model a traditional API based on classes which contain methods, and to define methods to do exactly one thing, and do it well. This results in a large command set but one that is relatively easy to understand.

The AMQP commands are grouped into classes. Each class covers a specific functional domain. Some classes are optional - each peer implements the classes it needs to support.

There are two distinct method dialogues:

  1. Synchronous request-response, in which one peer sends a request and the other peer sends a reply. Synchronous request and response methods are used for functionality that is not performance critical

  2. Asynchronous notification, in which one peer sends a method but expects no reply. Asynchronous methods are used where performance is critical.

To make method processing simple, we define distinct replies for each synchronous request. That is, no method is used as the reply for two different requests. This means that a peer, sending a synchronous request, can accept and process incoming methods until getting one of the valid synchronous replies. This differentiates AMQP from more traditional RPC protocols.

A method is formally defined as a synchronous request, a synchronous reply (to a specific request), or asynchronous. Lastly, each method is formally defined as being client-side (i.e. server to client), or server-side (client to server).

§ 3.2.2 Mapping AMQP to a middleware API

We have designed AMQP to be mappable to a middleware API. This mapping has some intelligence (not all methods, and not all arguments make sense to an application) but it is also mechanical (given some rules, all methods can be mapped without manual intervention).

The advantages of this are that having learnt the AMQP semantics (the classes that are described in this section), developers will find the same semantics provided in whatever environment they use.

For example, here is a Queue.Declare method example:

Queue.Declare
    queue=my.queue
    auto_delete=TRUE
    exclusive=FALSE

This can be cast as a wire-level frame:

     +--------+---------+----------+---------+---------+
     | Queue  | Declare | my.queue |    1    |    0    |
     +--------+---------+----------+---------+---------+
       class     method    name      autodel     excl.

Or as a higher-level API:

queue_declare (session, "my.queue", TRUE, FALSE);

Or as an abstract language:

<queue_declare name = "my.queue" auto_delete = "1" 
    exclusive = "FALSE" />

There are two main exceptions to making the entire protocol isomorphic with the client API:

  1. Existing API standards, such as JMS, which must be mapped manually onto the AMQP methods.

  2. Those AMQP methods concerned with connection and session start-up and shut-down, which are not useful to expose in the high-level API.

The pseudo-code logic for mapping an asynchronous method is:

send method to server

The pseudo-code logic for mapping a synchronous method is:

send request method to server
repeat
    wait for response from server
    if response is an asynchronous method
        process method (usually, delivered or returned content)
    else
        assert that method is a valid response for request
        exit repeat
    end-if
end-repeat

It is worth commenting that for most applications, middleware can be completely hidden in technical layers, and that the actual API used matters less than the fact that the middleware is robust and capable.

§ 3.2.3 No Confirmations

A chatty protocol is slow. We use asynchronism heavily in those cases where performance is an issue. This is generally where we send content from one peer to another. We send off methods as fast as possible, without waiting for confirmations. Where necessary, we implement windowing and throttling at a higher level, e.g. at the consumer level.

We can dispense with confirmations because we adopt an assertion model for all actions. Either they succeed, or we have an exception that closes the channel or connection.

There are no confirmations in AMQP. Success is silent, and failure is noisy. When applications need explicit tracking of success and failure, they should use transactions.

Note: This section does not apply to the request/response transport layer.

§ 3.2.4 The Content Classes

Following the principle of placing functional domains into distinct protocol classes that the server may or may not implement, AMQP also separates content processing into separate classes. The logic is that different types of content have different semantics. For example, basic messages and file transfer are quite different problems. We give each content type a class, and a set of methods that work with it.

AMQP currently defines three content classes:

  1. Basic contents, which implement standard messaging semantics.

  2. File contents, which support file-transfer semantics.

  3. Stream contents, which support data streaming semantics.

§ 3.3 Execution

TODO: edit for flow and consistency TODO: Incorporate text from 114.

Command ids will be assigned via an implicit sequence maintained by each peer. This sequence is a 32 bit number that begins at 0 with the first command received. These numbers are added and compared as defined by http://www.ietf.org/rfc/rfc1982.txt

Peers communicate using a bidirectional stream of commands. These commands are sent over a reliable, ordered transport. As a peer sends commands to its partner it must internally model its partner's expected state upon execution of the transmitted commands. A peer's model may be invalid for two reasons:

  1. Transport and processing introduce latency, so the partner's actual state may lag the peer's internal model.
  2. The actual state change resulting from executing the command may differ from the speculated state change.

The execution layer permits a peer to distinctly model the speculative and confirmed portions of its partner's state. Confirmation of completion is acheived by exchanging an execution-mark that identifies which commands have actually been processed by the partner. Additionally the execution layer provides a correlation mechanism that may be used by a partner to send commands that update the peer's speculative model when commands terminate abnormally. The correlation mechanism may also be used to provide early (out-of-order) transition of state changes from speculative to confirmed even when the speculative state changes are accurate.

The execution layer defines the following mechanims:

  1. A peer's execution mark is the highest number N such that commands 0-N received by that peer have all been processed.
  2. A peer may send an explicitly correlated command carrying the ID(s) of the original command(s) and information about the outcome. If the execution mark reaches a command before an explicitly correlated command is received then normal termination is assumed. If a command executes abnormally, there must always be a correlated response sent for that command before sending an execution mark at or above the command's ID.
  3. A peer may mark a command as requiring confirmation. (sync)
  4. A peer may send an out-of-band request for the current execution mark. (flush)

The execution layer depends on reliable, ordered transport of commands. This is not provided by the execution layer itself, but by the network transport layer. The diagram below illustrates the windows maintained by each layer:

                      Sender

                  execution mark
                         |
      +--confirmed proc--+--awaiting confirmation--+
      |                  |                         |
      +------------------+-------------------------+
      |  C1   |    C2    |   C3  |   C4  |    C5   |
      |--------------------------------------------|
      | F1 F2 | F3 F4 F5 | F6 F7 | F8 F9 | F10 F11 |----+
      +------------------------------+-------------+    |
      |                              |             |    |
      +-------confirmed recv---------+-transmitted-+    |
                                     |                  |
                             acknowledgment number      |
                                                        |
                                                    (Network)
                                                        |
                      Receiver                          |
                                                        |
      +----------------received----------------+        |
      |                                        |        |
      +----------------------------------------+        |
      | F1 F2 | F3 F4 F5 | F6 F7 | F8 F9 | F10 |<-------+
      |----------------------------------------+
      |  C1   |    C2    |   C3  |   C4  |
      +------------------+---------------+
      |                          |
      +---------processed--------+
C<n> the nth command
F<n> the nth frame
processed the receiver has executed the command
received the receiver has read the frame bytes
confirmed proc the sender knows the receiver has executed the command
confirmed recv the sender knows the receiver has read the frame bytes


Notes
Communication is symmetric, so each peer contains both the sending and receiving structures depicted above.

§ 3.3.1 Synchronization

The following information must be transmitted with each command.

command-id
A 32 bit sequence id.
execution-mark
A 32 bit number indicating the range of commands a peer has executed.
sync
Set to force the recipient to send the execution-mark on completion of the command.

The execution mark is a value maintained by each peer. This value is incremented after execution of each incoming command and sent with every outgoing command.

If the sending peer needs to block on execution of a given command it may set the sync bit. This requires the partner to send its execution-mark upon completion of the given command. The partner may piggy-back the execution-mark on any outgoing command, It may be necessary to issue a no-op command if there is no other outgoing command available.

An incoming command may carry information relevant to the disposition of a previous outgoing command, e.g. a message reject or command error code. A receiving peer must take this into account when processing the incoming execution-mark and a sending peer must take this into account when advancing the outgoing execution-mark.

§ 3.3.2 Flush

When commands flow primarily in one direction the sending peer may accumulate a large window of commands with an unknown disposition. An additional out-of-band flush signal is provided in order to permit the sending peer to request that the partner send the current execution-mark without waiting for currently transmitting or executing commands to finish. The partner may piggy-back the execution-mark on any outgoing command. It may be necessary to issue a no-op command if there is no other outgoing command available.

The following bit may be transmitted on any data frame:

flush
Set to signal the recipient to send the current execution-mark.

In later versions other mechanisms may be introduced to control the outstanding command window, e.g. there could be a negotiated count which if exceeded would require the broker to send the execution-mark. Such mechanisms are beyond the scope of this proposal and do not interfere with any of the functionality specified here.

§ 3.3.3 Correlation

The correlation context permits one to one or one to many correlation between commands. This allows a peer to send a command to its partner that efficiently references any number of commands previously sent by the partner. This context consists of a list of command ranges specified by a start id and an offset. In the special case where only one command is referenced the offset may be omitted.

correlation-context = one-to-one
                    / one-to-many

         one-to-one = command-id

        one-to-many = correlation-range*
  correlation-range = command-id offset

§ 3.3.4 Formal Definition

This is the logical description of the mini protocol used by the execution layer. This information must be injected into or annotated on top of the regular command stream:

         C(n): Command identification, indicates that the subsequent
               command has id n.

  DUP(ranges): Disposition update, indicates that the subsequent
               command updates the disposition of all C(n) for n in
               ranges. The range must not include commands previously
               marked complete.

       CEM(m): Cummulative execution mark, indicates that all
               C(n) is complete for n <= m.

  REM(ran