Azure Service Bus と Event Hubs における AMQP 1.0 プロトコル ガイドAMQP 1.0 in Azure Service Bus and Event Hubs protocol guide

Advanced Message Queueing Protocol 1.0 は、2 つの当事者間でメッセージを非同期で、安全かつ確実に転送することを目的に標準化されたフレーミングと転送のためのプロトコルです。The Advanced Message Queueing Protocol 1.0 is a standardized framing and transfer protocol for asynchronously, securely, and reliably transferring messages between two parties. Azure Service Bus メッセージングと Azure Event Hubs の主要なプロトコルとなっています。It is the primary protocol of Azure Service Bus Messaging and Azure Event Hubs. どちらのサービスも HTTPS をサポートしています。Both services also support HTTPS. 同じくサポートされている独自開発の SBMP プロトコルは今後、徐々に AMQP に置き換わっていく予定です。The proprietary SBMP protocol that is also supported is being phased out in favor of AMQP.

AMQP 1.0 は、ミドルウェア ベンダー (Microsoft、Red Hat など) と各種メッセージング ミドルウェア ユーザー (金融サービス業界を代表する JP モルガン・チェースなど) とを結び付ける、あまねく業界の協業の成果として生まれました。AMQP 1.0 is the result of broad industry collaboration that brought together middleware vendors, such as Microsoft and Red Hat, with many messaging middleware users such as JP Morgan Chase representing the financial services industry. AMQP プロトコルと拡張仕様の技術的な標準化は OASIS が担っており、今や国際標準の ISO/IEC 19494 として正式に認定されるに至っています。The technical standardization forum for the AMQP protocol and extension specifications is OASIS, and it has achieved formal approval as an international standard as ISO/IEC 19494.

目標Goals

この記事は、AMQP 1.0 メッセージング仕様の核となる概念を、現在 OASIS AMQP 技術委員会で最終承認に向けて調整されている一部の拡張仕様の草案と併せて簡単に紹介したものです。また、それらの仕様が Azure Service Bus でどのように実装され、構築されているかについても説明します。This article briefly summarizes the core concepts of the AMQP 1.0 messaging specification along with a small set of draft extension specifications that are currently being finalized in the OASIS AMQP technical committee and explains how Azure Service Bus implements and builds on these specifications.

この記事の目的は、あらゆるプラットフォームで既存の AMQP 1.0 クライアント スタックを使用している開発者が、AMQP 1.0 を介して Azure Service Bus と連携できるよう支援することです。The goal is for any developer using any existing AMQP 1.0 client stack on any platform to be able to interact with Azure Service Bus via AMQP 1.0.

広く普及している汎用 AMQP 1.0 スタック (Apache Proton、AMQP.NET Lite など) には既に、AMQP 1.0 の主要なプロトコルがすべて実装されています。Common general-purpose AMQP 1.0 stacks, such as Apache Proton or AMQP.NET Lite, already implement all core AMQP 1.0 protocols. こうした基礎となるジェスチャはしばしば、上位の API にラップされます。たとえば Apache Proton には実に 2 つの API が用意されています (命令型の Messenger API とリアクション型の Reactor API)。Those foundational gestures are sometimes wrapped with a higher-level API; Apache Proton even offers two, the imperative Messenger API and the reactive Reactor API.

以降の解説は、AMQP の接続とセッションとリンクの管理、さらにはフレーム転送の処理とフロー制御が、それぞれのスタック (Apache Proton-C など) で処理され、アプリケーションの開発者が気にかけるべき点は、たとえあってもごくわずかであることを想定しています。In the following discussion, we assume that the management of AMQP connections, sessions, and links and the handling of frame transfers and flow control are handled by the respective stack (such as Apache Proton-C) and do not require much if any specific attention from application developers. たとえば接続するための機能や、何らかの形態の抽象オブジェクトとして送信側受信側を作成する機能があって、そこに何らかの形でそれぞれ send() 操作と receive() 操作が存在するなど、概念上いくつかの基本的な API が存在するものとして話を進めます。We abstractly assume the existence of a few API primitives like the ability to connect, and to create some form of sender and receiver abstraction objects, which then have some shape of send() and receive() operations, respectively.

メッセージの読み取りやセッションの管理など、Azure Service Bus の高度な機能に触れる際は、AMQP の観点で説明しますが、これらの機能も、前提となる抽象化された API の上に階層化された擬似的な実装として解説します。When discussing advanced capabilities of Azure Service Bus, such as message browsing or management of sessions, those features are explained in AMQP terms, but also as a layered pseudo-implementation on top of this assumed API abstraction.

AMQP とは何かWhat is AMQP?

AMQP は、フレーミングと転送のプロトコルです。AMQP is a framing and transfer protocol. フレーミングとは、ネットワーク接続のいずれかの方向に流れるバイナリ データ ストリームに構造を与えることです。Framing means that it provides structure for binary data streams that flow in either direction of a network connection. 接続された当事者間で交換される、フレームと呼ばれる個々のデータ ブロックには、この構造によって輪郭が与えられます。The structure provides delineation for distinct blocks of data, called frames, to be exchanged between the connected parties. フレームをいつ転送するかや何をもって転送の完了と見なすかについて、通信を行う両方の当事者が共有の認識を持てるようにするのが、転送機能の役割となります。The transfer capabilities make sure that both communicating parties can establish a shared understanding about when frames shall be transferred, and when transfers shall be considered complete.

かつて AMQP の作業部会によって作成されて既に失効している草案版が今も、一部のメッセージ ブローカーで使用されています。しかし作業部会によって最終的に標準化された AMQP 1.0 プロトコルでは、こうした草案版とは異なり、メッセージ ブローカーの存在や、メッセージ ブローカー内のエンティティに対する特定のトポロジについては一切規定されていません。Unlike earlier expired draft versions produced by the AMQP working group that are still in use by a few message brokers, the working group's final, and standardized AMQP 1.0 protocol does not prescribe the presence of a message broker or any particular topology for entities inside a message broker.

このプロトコルは、ピア ツー ピアの対称な通信で、キュー エンティティや発行/購読エンティティをサポートするメッセージ ブローカー (Azure Service Bus など) との対話を目的として使用できます。The protocol can be used for symmetric peer-to-peer communication, for interaction with message brokers that support queues and publish/subscribe entities, as Azure Service Bus does. また、Azure Event Hubs のように、通常のキューと対話パターンの異なるメッセージング インフラストラクチャとの対話にも使用できます。It can also be used for interaction with messaging infrastructure where the interaction patterns are different from regular queues, as is the case with Azure Event Hubs. イベント ハブは、イベントを受け取る際にはキューのような働きをする一方、そこからイベントが読み取られるときには、シリアル ストレージ サービスのような働きをします。テープ ドライブとやや似た動作といってもいいでしょう。An Event Hub acts like a queue when events are sent to it, but acts more like a serial storage service when events are read from it; it somewhat resembles a tape drive. クライアントがデータ ストリームに対するオフセットを選ぶと、そのオフセットを起点として、ストリームの末尾まですべてのイベントがクライアントに配信されます。The client picks an offset into the available data stream and is then served all events from that offset to the latest available.

AMQP 1.0 プロトコルでは拡張性を意図した設計が採用され、さらなる仕様によって、その機能を拡張できるようになっています。The AMQP 1.0 protocol is designed to be extensible, enabling further specifications to enhance its capabilities. この点に関して、このドキュメントでは 3 つの拡張仕様を紹介しています。The three extension specifications discussed in this document illustrate this. 既存の Https/websocket インフラストラクチャ上の通信では、ネイティブの AMQP TCP ポートを構成することが難しいことがあります。For communication over existing HTTPS/WebSockets infrastructure, configuring the native AMQP TCP ports may be difficult. バインディング仕様では、Websocket 経由の AMQP を階層化する方法を定義します。A binding specification defines how to layer AMQP over WebSockets. 管理上の用途や高度な機能を実現することを目的とし、要求/応答の形式でメッセージング インフラストラクチャとやり取りするために必要な基本的な対話の要素は、AMQP Management 仕様に規定されています。For interacting with the messaging infrastructure in a request/response fashion for management purposes or to provide advanced functionality, the AMQP management specification defines the required basic interaction primitives. フェデレーション承認モデルの統合に関して、承認トークンをリンクに関連付けたり、リンクに関連付けられている承認トークンを更新したりする方法については、AMQP の CBS (Claims Based Security) 仕様で規定されています。For federated authorization model integration, the AMQP claims-based-security specification defines how to associate and renew authorization tokens associated with links.

基本的な AMQP のシナリオBasic AMQP scenarios

このセクションでは、Azure Service Bus での AMQP 1.0 の基本的な処理について説明します。接続やセッション、リンクを作成したり、Service Bus の各種エンティティ (キュー、トピック、サブスクリプションなど) との間でメッセージをやり取りしたりする方法を見ていきましょう。This section explains the basic usage of AMQP 1.0 with Azure Service Bus, which includes creating connections, sessions, and links, and transferring messages to and from Service Bus entities such as queues, topics, and subscriptions.

AMQP の動作について最も権威のある情報源は AMQP 1.0 仕様です。しかし仕様の目的は、実装上の指針を厳密に記述することであり、プロトコルについてわかりやすく解説することではありません。The most authoritative source to learn about how AMQP works is the AMQP 1.0 specification, but the specification was written to precisely guide implementation and not to teach the protocol. このセクションでは、Service Bus での AMQP 1.0 の使われ方を理解するうえで最低限必要な用語のみを紹介することに重点を置いています。This section focuses on introducing as much terminology as needed for describing how Service Bus uses AMQP 1.0. AMQP について大局的に扱った入門情報が必要な場合や、AMQP 1.0 についての広範な解説が必要である場合は、こちらのビデオ コースをご覧ください。For a more comprehensive introduction to AMQP, as well as a broader discussion of AMQP 1.0, you can review this video course.

接続とセッションConnections and sessions

AMQP は、"コンテナー" という通信プログラムを呼び出します。コンテナーには、その内部の通信エンティティである "ノード" が存在します。AMQP calls the communicating programs containers; those contain nodes, which are the communicating entities inside of those containers. キューは、そうしたノードの 1 つです。A queue can be such a node. AMQP は、多重化に対応しているため、1 本の接続をノード間の複数の通信経路で使用することが可能です。たとえばアプリケーション クライアントは、2 つのキューのうち、一方からは受信しながら、同時に同じネットワーク接続上でもう一方のキューに対して送信を行うことができます。AMQP allows for multiplexing, so a single connection can be used for many communication paths between nodes; for example, an application client can concurrently receive from one queue and send to another queue over the same network connection.

そのためネットワーク接続はコンテナーに固定されます。The network connection is thus anchored on the container. ネットワーク接続は、クライアント ロールのコンテナーによって開始されます。クライアント ロールのコンテナーが、受信側ロールのコンテナーに対して送信 TCP ソケット接続を確立し、受信側ロールは受信 TCP 接続を待機してそれを受け入れます。It is initiated by the container in the client role making an outbound TCP socket connection to a container in the receiver role, which listens for and accepts inbound TCP connections. 接続ハンドシェイクには、プロトコル バージョンのネゴシエーション、トランスポート レベルのセキュリティ (TLS/SSL) の使用に関する宣言 (またはネゴシエーション)、SASL に基づく接続スコープでの認証/承認ハンドシェイクが含まれます。The connection handshake includes negotiating the protocol version, declaring or negotiating the use of Transport Level Security (TLS/SSL), and an authentication/authorization handshake at the connection scope that is based on SASL.

Azure Service Bus では、常時 TLS の使用が必須となります。Azure Service Bus requires the use of TLS at all times. Azure Service Bus は、TCP ポート 5671 での接続に対応しています。これによって AMQP プロトコル ハンドシェイクに移行する前に、TCP 接続が TLS に重ね合わされます。また、Azure Service Bus は、TCP ポート 5672 での接続に対応しています。これによってサーバーは、AMQP に規定されたモデルに従って、TLS に必要な接続の更新を速やかに実施することができます。It supports connections over TCP port 5671, whereby the TCP connection is first overlaid with TLS before entering the AMQP protocol handshake, and also supports connections over TCP port 5672 whereby the server immediately offers a mandatory upgrade of connection to TLS using the AMQP-prescribed model. AMQP WebSocket のバインディングでは、TCP ポート 443 上にトンネルが作成されます。このトンネルが AMQP の 5671 接続に相当します。The AMQP WebSockets binding creates a tunnel over TCP port 443 that is then equivalent to AMQP 5671 connections.

Service Bus では、接続と TLS のセットアップ後、SASL の機構に関して次の 2 つの選択肢が用意されています。After setting up the connection and TLS, Service Bus offers two SASL mechanism options:

  • SASL PLAIN: ユーザー名とパスワードの資格情報をサーバーに渡す目的で一般的に使用されます。SASL PLAIN is commonly used for passing username and password credentials to a server. Service Bus はアカウントを持ちませんが、Shared Access Security の規則が指定されます。Shared Access Security の規則によって権限は付与され、また、この規則にキーが関連付けられます。Service Bus does not have accounts, but named Shared Access Security rules, which confer rights and are associated with a key. 規則の名前はユーザー名として使用され、キー (base64 エンコード テキスト) はパスワードとして使用されます。The name of a rule is used as the user name and the key (as base64 encoded text) is used as the password. 選択した規則に関連付けられている権限によって、対象の接続上で許可される操作が管理されます。The rights associated with the chosen rule govern the operations allowed on the connection.
  • SASL ANONYMOUS: 後述の CBS (Claims Based Security) モデルの使用をクライアントが希望しているとき、SASL の承認をバイパスする場合に使用します。SASL ANONYMOUS is used for bypassing SASL authorization when the client wants to use the claims-based-security (CBS) model that is described later. この方法を選択した場合、クライアント接続を短時間、匿名で確立することができます。その間にクライアントが対話できるのは CBS エンドポイントのみです。また、CBS ハンドシェイクも、その間に完了する必要があります。With this option, a client connection can be established anonymously for a short time during which the client can only interact with the CBS endpoint and the CBS handshake must complete.

トランスポート接続が確立された後、コンテナーはそれぞれ、処理する最大フレーム サイズを宣言し、その接続でアクティビティが存在しなければ、アイドル タイムアウトの経過後、一方的に接続を解除します。After the transport connection is established, the containers each declare the maximum frame size they are willing to handle, and after an idle timeout they’ll unilaterally disconnect if there is no activity on the connection.

またコンテナーは、同時にサポートされるチャネルの数も宣言します。They also declare how many concurrent channels are supported. チャネルは、接続の上に形成される内から外に向かう一方向の仮想的な転送経路です。A channel is a unidirectional, outbound, virtual transfer path on top of the connection. セッションは、相互接続された個々のコンテナーからチャネルを取得して、双方向の通信経路を形成します。A session takes a channel from each of the interconnected containers to form a bi-directional communication path.

セッションには、ウィンドウ型のフロー制御モデルが採用されています。つまりセッションの作成時に、それぞれの当事者が、その受信ウィンドウに受け入れるフレームの数を宣言します。Sessions have a window-based flow control model; when a session is created, each party declares how many frames it is willing to accept into its receive window. 通信の当事者がフレームを交換する際、転送済みのフレームによってウィンドウが埋められていき、それが一杯になると、ウィンドウが flow パフォーマティブを使って拡張されるか、リセットされるまで転送は中止されます (パフォーマティブは、2 つの当事者間でやり取りされるプロトコル レベルのジェスチャに使用される AMQP 用語)。As the parties exchange frames, transferred frames fill that window and transfers stop when the window is full and until the window gets reset or expanded using the flow performative (performative is the AMQP term for protocol-level gestures exchanged between the two parties).

基本的にこのウィンドウ型のモデルは、TCP のウィンドウ型フロー制御の概念と似ていますが、ソケット内のセッション レベルの概念である点が異なります。This window-based model is roughly analogous to the TCP concept of window-based flow control, but at the session level inside the socket. このプロトコルの概念は、複数の同時セッションを可能にするものであり、ちょうど高速道路の追い越し車線のように、優先度の高いトラフィックが、抑制された通常のトラフィックを追い越すことができるようになっています。The protocol’s concept of allowing for multiple concurrent sessions exists so that high priority traffic could be rushed past throttled normal traffic, like on a highway express lane.

現在、Azure Service Bus では各接続につき厳密に 1 つのセッションが使用されます。Azure Service Bus currently uses exactly one session for each connection. Service Bus Standard と Event Hubs の場合、Service Bus の最大フレーム サイズは 262,144 バイト (256KB) です。The Service Bus maximum frame-size is 262,144 bytes (256-K bytes) for Service Bus Standard and Event Hubs. Service Bus Premium の場合は、これが 1,048,576 (1 MB) になります。It is 1,048,576 (1 MB) for Service Bus Premium. セッション レベルで特定のスロットル ウィンドウを Service Bus が強制的に適用することはありませんが、リンク レベルのフロー制御の一環として Service Bus は、ウィンドウを定期的にリセットします (次のセクションを参照)。Service Bus does not impose any particular session-level throttling windows, but resets the window regularly as part of link-level flow control (see the next section).

接続、チャネル、セッションは一時的にしか存在しません。Connections, channels, and sessions are ephemeral. 根底の接続がダウンした場合、接続、TLS トンネル、SASL 承認コンテキスト、セッションを再度確立する必要があります。If the underlying connection collapses, connections, TLS tunnel, SASL authorization context, and sessions must be reestablished.

AMQP では、メッセージがリンクを介して転送されます。AMQP transfers messages over links. リンクは、メッセージを一方向に転送することを目的としてセッション上に形成される通信経路です。転送ステータスのネゴシエーションは、接続された当事者どうしがリンクを介し、双方向に実行します。A link is a communication path created over a session that enables transferring messages in one direction; the transfer status negotiation is over the link and bi-directional between the connected parties.

リンクは、送信側または受信側のどちらのコンテナーからでも随時、既存のセッション上に作成できます。これは、転送とその経路の開始が、ソケット接続を作成した当事者にのみ許可される HTTP や MQTT などの他の多くのプロトコルと AMQP が異なる点です。Links can be created by either container at any time and over an existing session, which makes AMQP different from many other protocols, including HTTP and MQTT, where the initiation of transfers and transfer path is an exclusive privilege of the party creating the socket connection.

リンクを開始したコンテナーは、もう一方のコンテナーにリンクを受け入れるよう要求すると共に、送信側と受信側のどちらかのロールを選択します。The link-initiating container asks the opposite container to accept a link and it chooses a role of either sender or receiver. したがって、どちらのコンテナーからでも一方向または双方向の通信経路の作成を開始することができます。この双方向の通信経路がリンクのペアとしてモデル化されています。Therefore, either container can initiate creating unidirectional or bi-directional communication paths, with the latter modeled as pairs of links.

リンクは名前を持ち、ノードに関連付けられます。Links are named and associated with nodes. 冒頭で述べたようにノードは、コンテナー内で通信を行うエンティティです。As stated in the beginning, nodes are the communicating entities inside a container.

Service Bus におけるノードは、キューやトピック、サブスクリプション (またはキューやサブスクリプションの配信不能サブキュー) と一対一で対応します。In Service Bus, a node is directly equivalent to a queue, a topic, a subscription, or a deadletter subqueue of a queue or subscription. そのため AMQP で使用されるノード名は、Service Bus の名前空間内のエンティティの相対名になります。The node name used in AMQP is therefore the relative name of the entity inside of the Service Bus namespace. キューに myqueue という名前を付けた場合、その名前は AMQP のノード名にもなります。If a queue is named myqueue, that’s also its AMQP node name. トピックのサブスクリプションは HTTP API の命名規則を踏襲し、"subscriptions" というリソース コレクションに分類されます。したがって、サブスクリプションが sub で、トピックが mytopic である場合、対応する AMQP ノード名は mytopic/subscriptions/sub となります。A topic subscription follows the HTTP API convention by being sorted into a "subscriptions" resource collection and thus, a subscription sub on a topic mytopic has the AMQP node name mytopic/subscriptions/sub.

ローカル ノード名は、接続する側のクライアントがリンクを作成するときにも必要となります。つまり Service Bus は、こうしたノード名について関与せず、そもそもノード名を解釈しません。The connecting client is also required to use a local node name for creating links; Service Bus is not prescriptive about those node names and does not interpret them. AMQP 1.0 クライアント スタックが、そのクライアントのスコープにおいてこれらの短期ノード名に重複がないことを特定のスキームを使って保証するのが一般的です。AMQP 1.0 client stacks generally use a scheme to assure that these ephemeral node names are unique in the scope of the client.

転送Transfers

リンクが確立されると、そのリンク上でメッセージを転送できる状態となります。Once a link has been established, messages can be transferred over that link. AMQP では、送信側からリンクを介して受信側にメッセージを移動する明示的なプロトコル ジェスチャ (transfer パフォーマティブ) によって転送が実行されます。In AMQP, a transfer is executed with an explicit protocol gesture (the transfer performative) that moves a message from sender to receiver over a link. 転送は、その結果についての共通認識が両者の間に確立されたことを意味する "settled (解決済み)" の状態になったときに完了します。A transfer is complete when it is “settled”, meaning that both parties have established a shared understanding of the outcome of that transfer.

最も単純なケースとして、送信側はメッセージを "未解決" の状態で送信することができます。これはクライアントが転送の結果に関心がなく、受信側からは、その操作の結果についてのフィードバックが一切得られないことを意味します。In the simplest case, the sender can choose to send messages "pre-settled," meaning that the client isn’t interested in the outcome and the receiver does not provide any feedback about the outcome of the operation. このモードは、Service Bus により AMQP プロトコル レベルでサポートされますが、いずれのクライアント API にも公開されていません。This mode is supported by Service Bus at the AMQP protocol level, but not exposed in any of the client APIs.

通常のケースでは、未解決の状態で送信されたメッセージに対して、受信側が disposition パフォーマティブを使用して受理または拒否を表明します。The regular case is that messages are being sent unsettled, and the receiver then indicates acceptance or rejection using the disposition performative. 拒否されるのは、受信側が何らかの理由でメッセージを受け入れることができないときです。拒否されたメッセージには、その理由についての情報 (AMQP によって定義されたエラーの構造体) が格納されます。Rejection occurs when the receiver cannot accept the message for any reason, and the rejection message contains information about the reason, which is an error structure defined by AMQP. Service Bus の内部的なエラーが原因でメッセージが拒否された場合、追加情報が構造体に格納されてサービスから返されます。サポート リクエストを申請する場合は、この構造体を使用して、診断の手掛かりをサポート担当者に提出することができます。If messages are rejected due to internal errors inside of Service Bus, the service returns extra information inside that structure that can be used for providing diagnostics hints to support personnel if you are filing support requests. エラーについては、後ほど詳しく説明します。You learn more details about errors later.

特殊な拒否の形態として released 状態があります。これは、その転送に反対する技術的な理由が受信側にあるわけではないものの、転送を解決することにも関心がないことを意味します。A special form of rejection is the released state, which indicates that the receiver has no technical objection to the transfer, but also no interest in settling the transfer. たとえば、Service Bus クライアントにメッセージが配信されたとき、メッセージの配信そのものに問題があるわけではないものの、そのメッセージを処理することによって発生する作業を実行できないために、そのメッセージを "破棄" することをクライアントが選ぶケースです。That case exists, for example, when a message is delivered to a Service Bus client, and the client chooses to "abandon" the message because it cannot perform the work resulting from processing the message; the message delivery itself is not at fault. この状態のバリエーションとして modified があります。これは、released 状態のメッセージへの変更を許可するものです。A variation of that state is the modified state, which allows changes to the message as it is released. 現在のところ、Service Bus ではこの状態は使用されていません。That state is not used by Service Bus at present.

AMQP 1.0 仕様では、disposition 状態としてさらに received が規定されています。特にリンクの復旧処理に役立てられます。The AMQP 1.0 specification defines a further disposition state called received, that specifically helps to handle link recovery. 接続とセッションが失われた場合、リンクの復旧によって、接続とセッションを新たに作成し、その上にリンクの状態と保留中の配信を再構築することができます。Link recovery allows reconstituting the state of a link and any pending deliveries on top of a new connection and session, when the prior connection and session were lost.

Service Bus は、リンクの復旧をサポートしていません。クライアントと Service Bus との接続が喪失し、未解決のメッセージ転送が保留状態となった場合、そのメッセージ転送は失われます。この場合、クライアントは再度接続してリンクを確立し直し、転送を再試行する必要があります。Service Bus does not support link recovery; if the client loses the connection to Service Bus with an unsettled message transfer pending, that message transfer is lost, and the client must reconnect, reestablish the link, and retry the transfer.

そのようなこともあって、Service Bus と Event Hubs は "At Least Once (1 回以上)" 転送をサポートしています。こうして、送信側は、メッセージが保存され受け付けられたことを確信することができます。ただし、AMQP レベル (メッセージ転送の重複を回避するために、リンクを復旧し、配信状態をネゴシエートし続ける) での "Exactly Once (1 回限り)" 転送はサポートされていません。As such, Service Bus and Event Hubs support "at least once" transfer where the sender can be assured for the message having been stored and accepted, but do not support "exactly once" transfers at the AMQP level, where the system would attempt to recover the link and continue to negotiate the delivery state to avoid duplication of the message transfer.

送信の重複のリスクを回避する手段として、Service Bus は、キューやトピックに対するオプション機能として重複検出をサポートしています。To compensate for possible duplicate sends, Service Bus supports duplicate detection as an optional feature on queues and topics. 重複検出では、ユーザー定義の時間内に受信したすべてのメッセージの ID が記録され、その時間内に同じ ID で送信されたメッセージはすべて警告なしで削除されます。Duplicate detection records the message IDs of all incoming messages during a user-defined time window, then silently drops all messages sent with the same message-IDs during that same window.

フロー制御Flow control

これまで説明してきたセッション レベルのフロー制御モデルに加え、各リンクには独自のフロー制御モデルが存在します。In addition to the session-level flow control model that previously discussed, each link has its own flow control model. セッション レベルのフロー制御は、一度に処理すべきフレーム数が多くなりすぎないようコンテナーを保護するものです。これに対し、リンク レベルのフロー制御では、そのリンクから受け取るメッセージの数とそのタイミングが、アプリケーションの管理下に置かれます。Session-level flow control protects the container from having to handle too many frames at once, link-level flow control puts the application in charge of how many messages it wants to handle from a link and when.

リンク上で転送が行われるのは、送信側に十分なリンク クレジットがあるときだけです。On a link, transfers can only happen when the sender has enough link credit. リンク クレジットは、受信側が flow パフォーマティブ (適用対象はリンク) を使って設定するカウンターです。Link credit is a counter set by the receiver using the flow performative, which is scoped to a link. 送信側は、自身にリンク クレジットが割り当てられているとき、メッセージを配信することでそのクレジットを消費します。When the sender is assigned link credit, it attempts to use up that credit by delivering messages. メッセージを配信するたびに、残りのリンク クレジットが 1 つ減らされます。Each message delivery decrements the remaining link credit by 1. リンク クレジットを使い果たすと、配信は停止します。When the link credit is used up, deliveries stop.

Service Bus は受信側ロールになるとすぐ、メッセージを直ちに送信できるよう送信側に対して十分なリンク クレジットを与えます。When Service Bus is in the receiver role, it instantly provides the sender with ample link credit, so that messages can be sent immediately. リンク クレジットが使用される過程で、Service Bus は送信側に対して、ときどき flow パフォーマティブを送信し、リンク クレジットの残数を更新します。As link credit is used, Service Bus occasionally sends a flow performative to the sender to update the link credit balance.

送信側ロールの Service Bus はメッセージを送信し、未使用のリンク クレジットを消費します。In the sender role, Service Bus sends messages to use up any outstanding link credit.

API レベルでの "receive" 呼び出しは、flow パフォーマティブに変換されて、クライアントから Service Bus に送信されます。Service Bus は、ロックされていない最初のメッセージをキューから取り出し、ロックして転送することによって、そのクレジットを消費します。A "receive" call at the API level translates into a flow performative being sent to Service Bus by the client, and Service Bus consumes that credit by taking the first available, unlocked message from the queue, locking it, and transferring it. すぐに配信できるメッセージが存在しない場合、その特定のエンティティとの間で確立されたリンクごとの未使用クレジットが到着順に記録されます。配信できるメッセージが到着して、未使用クレジットを使用できる状態になると、メッセージはロックされて転送されます。If there is no message readily available for delivery, any outstanding credit by any link established with that particular entity remains recorded in order of arrival, and messages are locked and transferred as they become available, to use any outstanding credit.

メッセージに対するロックは、その転送が acceptedrejectedreleased のいずれかの状態に解決されると解除されます。The lock on a message is released when the transfer is settled into one of the terminal states accepted, rejected, or released. 終端の状態が accepted であるとき、メッセージは Service Bus から削除されます。The message is removed from Service Bus when the terminal state is accepted. 転送の状態がそれ以外になった場合、メッセージは Service Bus に残り、次の受信者に配信されます。It remains in Service Bus and is delivered to the next receiver when the transfer reaches any of the other states. たび重なる reject または release でエンティティに割り当てられた最大配信カウントに達すると、メッセージは、Service Bus によって自動的にそのエンティティの配信不能キューに移動されます。Service Bus automatically moves the message into the entity's deadletter queue when it reaches the maximum delivery count allowed for the entity due to repeated rejections or releases.

現時点の Service Bus API にそのようなオプションは直接公開されていませんが、それよりも低レベルの AMQP プロトコル クライアントでは、リンク クレジット モデルを使用すれば、receive 要求ごとに 1 単位のクレジットを発行する "プル式" の対話を "プッシュ式" のモデルに変えることができます。つまり、リンク クレジットを大量に発行しておき、メッセージが利用可能になったときに、それ以上の対話操作を行わなくてもそれらのメッセージを受信できるようなモデルを実現できます。Even though the Service Bus APIs do not directly expose such an option today, a lower-level AMQP protocol client can use the link-credit model to turn the "pull-style" interaction of issuing one unit of credit for each receive request into a "push-style" model by issuing a large number of link credits and then receive messages as they become available without any further interaction. プッシュは、MessagingFactory.PrefetchCount プロパティまたは MessageReceiver.PrefetchCount プロパティの設定を通じてサポートされます。Push is supported through the MessagingFactory.PrefetchCount or MessageReceiver.PrefetchCount property settings. これらの設定が 0 以外であるとき、AMQP クライアントでリンク クレジットとして使用されます。When they are non-zero, the AMQP client uses it as the link credit.

このとき、エンティティ内のメッセージに対するロックの有効期限は、メッセージが通信回線上に送り出されたときではなく、エンティティからメッセージを取得したときを起点として計時されることに注意してください。In this context, it's important to understand that the clock for the expiration of the lock on the message inside the entity starts when the message is taken from the entity, not when the message is put on the wire. メッセージを受信する用意ができていることをクライアントがリンク クレジットを発行することによって表明したときは常に、当然そのネットワークを介して能動的にメッセージをプルしようとしていること、またそれらを処理する準備が整っているものと解釈されます。Whenever the client indicates readiness to receive messages by issuing link credit, it is therefore expected to be actively pulling messages across the network and be ready to handle them. それ以外の場合、メッセージが配信される前に、メッセージに対するロックの有効期限が切れます。Otherwise the message lock may have expired before the message is even delivered. リンク クレジットによるフロー制御は、送り出された有効なメッセージを受信側がすぐに処理できることを前提としています。The use of link-credit flow control should directly reflect the immediate readiness to deal with available messages dispatched to the receiver.

以降のセクションでは、各種 API 操作におけるパフォーマティブの流れを大まかに説明します。In summary, the following sections provide a schematic overview of the performative flow during different API interactions. セクションごとに異なる論理操作について説明しています。Each section describes a different logical operation. そうした対話操作の中には、必要になったときにしか実行されない "緩慢" な処理もあります。Some of those interactions may be "lazy," meaning they may only be performed when required. メッセージの送信側を作成しても、最初のメッセージが送信または要求されるまで、ネットワークの対話が実行されない場合があります。Creating a message sender may not cause a network interaction until the first message is sent or requested.

次の表の矢印は、パフォーマティブのフロー方向を示しています。The arrows in the following table show the performative flow direction.

メッセージの受信側の作成Create message receiver

ClientClient Service BusService Bus
--> attach(--> attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=receiver,role=receiver,
source={entity name},source={entity name},
target={client link ID}target={client link ID}
))
クライアントがエンティティに受信側として接続Client attaches to entity as receiver
Service Bus がそのリンクの終端を接続して応答Service Bus replies attaching its end of the link <-- attach(<-- attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=sender,role=sender,
source={entity name},source={entity name},
target={client link ID}target={client link ID}
))

メッセージの送信側の作成Create message sender

ClientClient Service BusService Bus
--> attach(--> attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=sender,role=sender,
source={client link ID},source={client link ID},
target={entity name}target={entity name}
))
アクションなしNo action
アクションなしNo action <-- attach(<-- attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=receiver,role=receiver,
source={client link ID},source={client link ID},
target={entity name}target={entity name}
))

メッセージの送信側の作成 (エラー)Create message sender (error)

ClientClient Service BusService Bus
--> attach(--> attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=sender,role=sender,
source={client link ID},source={client link ID},
target={entity name}target={entity name}
))
アクションなしNo action
アクションなしNo action <-- attach(<-- attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=receiver,role=receiver,
source=null,source=null,
target=nulltarget=null
))

<-- detach(<-- detach(
handle={numeric handle},handle={numeric handle},
closed=true,closed=true,
error={error info}error={error info}
))

メッセージ受信側/送信側のクローズClose message receiver/sender

ClientClient Service BusService Bus
--> detach(--> detach(
handle={numeric handle},handle={numeric handle},
closed=trueclosed=true
))
アクションなしNo action
アクションなしNo action <-- detach(<-- detach(
handle={numeric handle},handle={numeric handle},
closed=trueclosed=true
))

送信 (成功)Send (success)

ClientClient Service BusService Bus
--> transfer(--> transfer(
delivery-id={numeric handle},delivery-id={numeric handle},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,,more=false,settled=false,,more=false,
state=null,state=null,
resume=falseresume=false
))
アクションなしNo action
アクションなしNo action <-- disposition(<-- disposition(
role=receiver,role=receiver,
first={delivery ID},first={delivery ID},
last={delivery ID},last={delivery ID},
settled=true,settled=true,
state=acceptedstate=accepted
))

送信 (エラー)Send (error)

ClientClient Service BusService Bus
--> transfer(--> transfer(
delivery-id={numeric handle},delivery-id={numeric handle},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,,more=false,settled=false,,more=false,
state=null,state=null,
resume=falseresume=false
))
アクションなしNo action
アクションなしNo action <-- disposition(<-- disposition(
role=receiver,role=receiver,
first={delivery ID},first={delivery ID},
last={delivery ID},last={delivery ID},
settled=true,settled=true,
state=rejected(state=rejected(
error={error info}error={error info}
))
))

受信Receive

ClientClient Service BusService Bus
--> flow(--> flow(
link-credit=1link-credit=1
))
アクションなしNo action
アクションなしNo action < transfer(< transfer(
delivery-id={numeric handle},delivery-id={numeric handle},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,settled=false,
more=false,more=false,
state=null,state=null,
resume=falseresume=false
))
--> disposition(--> disposition(
role=receiver,role=receiver,
first={delivery ID},first={delivery ID},
last={delivery ID},last={delivery ID},
settled=true,settled=true,
state=acceptedstate=accepted
))
アクションなしNo action

複数メッセージの受信Multi-message receive

ClientClient Service BusService Bus
--> flow(--> flow(
link-credit=3link-credit=3
))
アクションなしNo action
アクションなしNo action < transfer(< transfer(
delivery-id={numeric handle},delivery-id={numeric handle},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,settled=false,
more=false,more=false,
state=null,state=null,
resume=falseresume=false
))
アクションなしNo action < transfer(< transfer(
delivery-id={numeric handle+1},delivery-id={numeric handle+1},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,settled=false,
more=false,more=false,
state=null,state=null,
resume=falseresume=false
))
アクションなしNo action < transfer(< transfer(
delivery-id={numeric handle+2},delivery-id={numeric handle+2},
delivery-tag={binary handle},delivery-tag={binary handle},
settled=false,settled=false,
more=false,more=false,
state=null,state=null,
resume=falseresume=false
))
--> disposition(--> disposition(
role=receiver,role=receiver,
first={delivery ID},first={delivery ID},
last={delivery ID+2},last={delivery ID+2},
settled=true,settled=true,
state=acceptedstate=accepted
))
アクションなしNo action

メッセージMessages

以降のセクションでは、標準 AMQP メッセージ セクションから、Service Bus でどのプロパティが使用され、Service Bus API セットに対してどのように対応付けられるかを説明します。The following sections explain which properties from the standard AMQP message sections are used by Service Bus and how they map to the Service Bus API set.

アプリケーションで定義する必要があるプロパティはすべて、AMQP の application-properties マップにマッピングされる必要があります。Any property that application needs to defines should be mapped to AMQP's application-properties map.

フィールド名Field Name 使用法Usage API 名API name
durabledurable - -
prioritypriority - -
ttlttl このメッセージの有効期限Time to live for this message TimeToLiveTimeToLive
first-acquirerfirst-acquirer - -
delivery-countdelivery-count - DeliveryCountDeliveryCount

propertiesproperties

フィールド名Field Name 使用法Usage API 名API name
message-idmessage-id このメッセージに対するアプリケーション定義の自由形式 ID。Application-defined, free-form identifier for this message. 重複検出に使用されます。Used for duplicate detection. MessageIdMessageId
user-iduser-id アプリケーション定義のユーザー ID。Service Bus では解釈されません。Application-defined user identifier, not interpreted by Service Bus. Service Bus API を介してアクセスすることはできません。Not accessible through the Service Bus API.
toto アプリケーション定義の送信先 ID。Service Bus では解釈されません。Application-defined destination identifier, not interpreted by Service Bus. ToTo
subjectsubject アプリケーション定義のメッセージ用途 ID。Service Bus では解釈されません。Application-defined message purpose identifier, not interpreted by Service Bus. LabelLabel
reply-toreply-to アプリケーション定義の応答パス ID。Service Bus では解釈されません。Application-defined reply-path indicator, not interpreted by Service Bus. ReplyToReplyTo
correlation-idcorrelation-id アプリケーション定義の相関関係 ID。Service Bus では解釈されません。Application-defined correlation identifier, not interpreted by Service Bus. CorrelationIdCorrelationId
content-typecontent-type アプリケーション定義の本文コンテンツ タイプ ID。Service Bus では解釈されません。Application-defined content-type indicator for the body, not interpreted by Service Bus. ContentTypeContentType
content-encodingcontent-encoding アプリケーション定義の本文コンテンツ エンコーディング ID。Service Bus では解釈されません。Application-defined content-encoding indicator for the body, not interpreted by Service Bus. Service Bus API を介してアクセスすることはできません。Not accessible through the Service Bus API.
absolute-expiry-timeabsolute-expiry-time メッセージの有効期限が切れる絶対時刻を宣言します。Declares at which absolute instant the message expires. 入力時には無視され (ヘッダーの TTL が優先され)、出力時に強制力を持ちます。Ignored on input (header TTL is observed), authoritative on output. ExpiresAtUtcExpiresAtUtc
creation-timecreation-time メッセージが作成された時刻を宣言します。Declares at which time the message was created. Service Bus では使用されません。Not used by Service Bus Service Bus API を介してアクセスすることはできません。Not accessible through the Service Bus API.
group-idgroup-id 関連する一連のメッセージに対するアプリケーション定義の ID。Application-defined identifier for a related set of messages. Service Bus のセッションに使用されます。Used for Service Bus sessions. SessionIdSessionId
group-sequencegroup-sequence セッション内のメッセージの相対シーケンス番号を識別するカウンター。Counter identifying the relative sequence number of the message inside a session. Service Bus では無視されます。Ignored by Service Bus. Service Bus API を介してアクセスすることはできません。Not accessible through the Service Bus API.
reply-to-group-idreply-to-group-id - ReplyToSessionIdReplyToSessionId

メッセージの注釈Message annotations

AMQP メッセージ プロパティの一部ではなく、かつ、メッセージ上で MessageAnnotations として渡される他の Service Bus メッセージはほとんどありません。There are few other service bus message properties, which are not part of AMQP message properties, and are passed along as MessageAnnotations on the message.

注釈マップ キーAnnotation Map Key 使用法Usage API 名API name
x-opt-scheduled-enqueue-timex-opt-scheduled-enqueue-time メッセージがエンティティ上に出現する時刻を宣言します。Declares at which time the message should appear on the entity ScheduledEnqueueTimeScheduledEnqueueTime
x-opt-partition-keyx-opt-partition-key メッセージを受信するパーティションを指示する、アプリケーションで定義されたキー。Application-defined key that dictates which partition the message should land in. PartitionKeyPartitionKey
x-opt-via-partition-keyx-opt-via-partition-key 転送キュー経由でメッセージを送信するためにトランザクションが使用される場合の、アプリケーションで定義されたパーティション キーの値。Application-defined partition-key value when a transaction is to be used to send messages via a transfer queue. ViaPartitionKeyViaPartitionKey
x-opt-enqueued-timex-opt-enqueued-time メッセージをエンキューする実際の時刻を表す、サービスで定義された UTC 時刻。Service-defined UTC time representing the actual time of enqueuing the message. インポート時には無視されます。Ignored on input. EnqueuedTimeUtcEnqueuedTimeUtc
x-opt-sequence-numberx-opt-sequence-number メッセージに割り当てられる、サービスで定義された一意の番号。Service-defined unique number assigned to a message. SequenceNumberSequenceNumber
x-opt-offsetx-opt-offset サービスで定義された、エンキューされるメッセージのシーケンス番号。Service-defined enqueued sequence number of the message. EnqueuedSequenceNumberEnqueuedSequenceNumber
x-opt-locked-untilx-opt-locked-until サービスで定義される。Service-defined. メッセージがキュー/サブスクリプションでロックされるまでの日時。The date and time until which the message will be locked in the queue/subscription. LockedUntilUtcLockedUntilUtc
x-opt-deadletter-sourcex-opt-deadletter-source サービスで定義される。Service-Defined. 配信不能キューからメッセージが受信された場合の、元のメッセージのソース。If the message is received from dead letter queue, the source of the original message. DeadLetterSourceDeadLetterSource

トランザクション機能Transaction capability

トランザクションにより、複数の操作が 1 つの実行スコープにグループ化されます。A transaction groups two or more operations together into an execution scope. 性質上、このようなトランザクションによって、操作の特定のグループに属する操作がすべて成功するか、すべて失敗するかのいずれかになる必要があります。By nature, such a transaction must ensure that all operations belonging to a given group of operations either succeed or fail jointly. 操作は、識別子 txn-id によってグループ化されます。The operations are grouped by an identifier txn-id.

トランザクション操作の場合、クライアントは、グループ化する必要がある操作を制御する transaction controller として機能します。For transactional interaction, the client acts as a transaction controller , which controls the operations that should be grouped together. Service Bus サービスは、transactional resource として機能し、transaction controller による要求に従って作業を実行します。Service Bus Service acts as a transactional resource and performs work as requested by the transaction controller.

クライアントとサービスは、クライアントによって確立された control link 経由で通信します。The client and service communicate over a control link , which is established by the client. declare および discharge メッセージは、トランザクションを個別に割り当てて完了するために、制御リンク経由でコントローラーから送信されます (トランザクション作業の区別を表しているわけではありません)。The declare and discharge messages are sent by the controller over the control link to allocate and complete transactions respectively (they do not represent the demarcation of transactional work). 実際の送受信は、このリンク上では実行されません。The actual send/receive is not performed on this link. 要求された各トランザクション操作は、目的の txn-id によって明示的に識別されるため、接続上の任意のリンクで実行される可能性があります。Each transactional operation requested is explicitly identified with the desired txn-id and therefore may occur on any link on the Connection. 作成した未送信のトランザクションが存在するときに、制御リンクが閉じられると、このようなトランザクションはすべて、ただちにローグバックされ、これらに対してさらにトランザクション作業の実行を試行した場合は、エラーが発生します。If the control link is closed while there exist non-discharged transactions it created, then all such transactions are immediately rolled back, and attempts to perform further transactional work on them will lead to failure. 制御リンク上のメッセージが事前に確定されることはありません。Messages on control link must not be pre settled.

どの接続でも、独自の制御リンクを開始して、トランザクションを開始および終了できる必要があります。Every connection has to initiate its own control link to be able to start and end transactions. サービスは、coordinator として機能する専用のターゲットを定義します。The service defines a special target that functions as a coordinator. クライアント/コントローラーは、このターゲットへの制御リンクを確立します。The client/controller establishes a control link to this target. 制御リンクは、エンティティの境界の外にあります。つまり、複数のエンティティに対するトランザクションの開始と送信に、同じ制御リンクを使用できます。Control link is outside the boundary of an entity, that is, same control link can be used to initiate and discharge transactions for multiple entities.

トランザクションの開始Starting a transaction

トランザクションの作業を開始するには、To begin transactional work. コントローラーがコーディネータから txn-id を取得する必要があります。the controller must obtain a txn-id from the coordinator. declare 型のメッセージを送信することで、これを行います。It does this by sending a declare type message. 宣言が成功すると、コーディネーターは処理出力で応答し、それを通じて、割り当てられた txn-id が伝えられます。If the declaration is successful, the coordinator responds with a disposition outcome, which carries the assigned txn-id.

クライアント (コント ローラー)Client (Controller) Service Bus (コーディネーター)Service Bus (Coordinator)
attach(attach(
name={link name},name={link name},
... ,... ,
role=sender,role=sender,
target=Coordinatortarget=Coordinator
))
------>
<------ attach(attach(
name={link name},name={link name},
... ,... ,
target=Coordinator()target=Coordinator()
))
transfer(transfer(
delivery-id=0, ...)delivery-id=0, ...)
{ AmqpValue (Declare() )}{ AmqpValue (Declare())}
------>
<------ disposition(disposition(
first=0, last=0,first=0, last=0,
state=Declared(state=Declared(
txn-id={transaction ID}txn-id={transaction ID}
))))

トランザクションの送信Discharging a transaction

コントローラーは、discharge メッセージをコーディネーターに送信することで、トランザクション作業を完結します。The controller concludes the transactional work by sending a discharge message to the coordinator. コントローラーは、送信の本文に fail フラグを設定することでトランザクション作業をコミットまたはロールバックしようとしていることを示します。The controller indicates that it wishes to commit or roll back the transactional work by setting the fail flag on the discharge body. コーディネーターが送信を完了できない場合、transaction-error を伝送する次のような出力と共にメッセージが拒否されます。If the coordinator is unable to complete the discharge, the message is rejected with this outcome carrying the transaction-error.

注: fail=true はトランザクションのロールバックを示し、fail=false はコミットを示します。Note: fail=true refers to Rollback of a transaction, and fail=false refers to Commit.

クライアント (コント ローラー)Client (Controller) Service Bus (コーディネーター)Service Bus (Coordinator)
transfer(transfer(
delivery-id=0, ...)delivery-id=0, ...)
{ AmqpValue (Declare())}{ AmqpValue (Declare())}
------>
<------ disposition(disposition(
first=0, last=0,first=0, last=0,
state=Declared(state=Declared(
txn-id={transaction ID}txn-id={transaction ID}
))))
. .. .
トランザクション作業Transactional work
(別のリンク上で)on other links
. .. .
transfer(transfer(
delivery-id=57, ...)delivery-id=57, ...)
{ AmqpValue ({ AmqpValue (
Discharge(txn-id=0,
fail=false)
)}
Discharge(txn-id=0,
fail=false)
)}
------>
<------ disposition(disposition(
first=57, last=57,first=57, last=57,
state=Accepted() )state=Accepted())

トランザクションでのメッセージの送信Sending a message in a transaction

すべてのトランザクション作業は、txn-id を伝送するトランザクションの配信ステータス transactional-state を使って行われます。メッセージを送信する場合は、トランザクションのステータスは、メッセージの転送フレームによって伝送されます。All transactional work is done with the transactional delivery state transactional-state that carries the txn-id. In the case of sending messages, the transactional-state is carried by the message's transfer frame.

クライアント (コント ローラー)Client (Controller) Service Bus (コーディネーター)Service Bus (Coordinator)
transfer(transfer(
delivery-id=0, ...)delivery-id=0, ...)
{ AmqpValue (Declare())}{ AmqpValue (Declare())}
------>
<------ disposition(disposition(
first=0, last=0,first=0, last=0,
state=Declared(state=Declared(
txn-id={transaction ID}txn-id={transaction ID}
))))
transfer(transfer(
handle=1,handle=1,
delivery-id=1,delivery-id=1,
state=
TransactionalState(
txn-id=0)
)
state=
TransactionalState(
txn-id=0)
)

{ payload }{ payload }
------>
<------ disposition(disposition(
first=1, last=1,first=1, last=1,
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))

トランザクションでのメッセージの処理Disposing a message in a transaction

メッセージの処理には、Complete / Abandon / DeadLetter / Defer のような操作が含まれています。Message disposition includes operations like Complete / Abandon / DeadLetter / Defer. トランザクションの中でこれらの操作を実行するには、disposition を使って transactional-state を渡します。To perform these operations within a transaction, pass the transactional-state with the disposition.

クライアント (コント ローラー)Client (Controller) Service Bus (コーディネーター)Service Bus (Coordinator)
transfer(transfer(
delivery-id=0, ...)delivery-id=0, ...)
{ AmqpValue (Declare())}{ AmqpValue (Declare())}
------>
<------ disposition(disposition(
first=0, last=0,first=0, last=0,
state=Declared(state=Declared(
txn-id={transaction ID}txn-id={transaction ID}
))))
<------ transfer(transfer(
handle=2,handle=2,
delivery-id=11,delivery-id=11,
state=null)state=null)
{ payload }{ payload }
disposition(disposition(
first=11, last=11,first=11, last=11,
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))
state=TransactionalState(
txn-id=0,
outcome=Accepted()
))
------>

Advanced Service Bus の機能Advanced Service Bus capabilities

このセクションでは、現在 AMQP の OASIS 技術委員会で策定が進められている AMQP の拡張機能の草案に基づく Azure Service Bus の高度な機能について取り上げます。This section covers advanced capabilities of Azure Service Bus that are based on draft extensions to AMQP, currently being developed in the OASIS Technical Committee for AMQP. Service Bus には、最新バージョンの草案が実装されています。変更は、草案が標準ステータスになった時点で採用される見込みです。Service Bus implements the latest versions of these drafts and adopts changes introduced as those drafts reach standard status.

注意

Service Bus Messaging の高度な操作は、要求/応答パターンを介してサポートされます。Service Bus Messaging advanced operations are supported through a request/response pattern. これらの操作の詳細は、「AMQP 1.0 in Service Bus: request/response-based operations (Service Bus の AMQP 1.0: 要求応答ベースの操作)」の記事に説明されています。The details of these operations are described in the article AMQP 1.0 in Service Bus: request-response-based operations.

AMQP ManagementAMQP management

草案段階の拡張機能として、この記事ではまず AMQP Management 仕様について説明します。The AMQP management specification is the first of the draft extensions discussed in this article. この仕様には、メッセージング インフラストラクチャに対して AMQP を介して管理操作を行うための、AMQP プロトコル上に階層化された一連のプロトコルが定義されています。This specification defines a set of protocols layered on top of the AMQP protocol that allow management interactions with the messaging infrastructure over AMQP. 仕様で定義されているのは、createreadupdatedelete など、メッセージング インフラストラクチャ内のエンティティを管理するための一般的な操作と一連のクエリ操作です。The specification defines generic operations such as create, read, update, and delete for managing entities inside a messaging infrastructure and a set of query operations.

これらのジェスチャにはいずれも、クライアントとメッセージング インフラストラクチャとの間で要求/応答の対話を伴います。そのため、この仕様には、その対話パターンを AMQP 上にモデル化する方法 (つまりクライアントがメッセージング インフラストラクチャに接続し、セッションを開始した後、リンクのペアを作成する) が定義されています。All those gestures require a request/response interaction between the client and the messaging infrastructure, and therefore the specification defines how to model that interaction pattern on top of AMQP: the client connects to the messaging infrastructure, initiates a session, and then creates a pair of links. クライアントは、一方のリンクでは送信側として機能し、もう一方のリンクでは受信側として機能します。こうして形成された一対のリンクが双方向チャネルとしての役割を果たします。On one link, the client acts as sender and on the other it acts as receiver, thus creating a pair of links that can act as a bi-directional channel.

論理操作Logical Operation ClientClient Service BusService Bus
要求の応答経路を作成Create Request Response Path --> attach(--> attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=sender,role=sender,
source=null,source=null,
target=”myentity/$management”target=”myentity/$management”
))
アクションなしNo action
要求の応答経路を作成Create Request Response Path アクションなしNo action <-- attach(<-- attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=receiver,role=receiver,
source=null,source=null,
target=”myentity”target=”myentity”
))
要求の応答経路を作成Create Request Response Path --> attach(--> attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=receiver,role=receiver,
source=”myentity/$management”,source=”myentity/$management”,
target=”myclient$id”target=”myclient$id”
))
要求の応答経路を作成Create Request Response Path アクションなしNo action <-- attach(<-- attach(
name={link name},name={link name},
handle={numeric handle},handle={numeric handle},
role=sender,role=sender,
source=”myentity”,source=”myentity”,
target=”myclient$id”target=”myclient$id”
))

リンクのペアが作成されていれば、要求/応答の実装は簡単です。つまり要求とはメッセージであり、そのパターンを認識するメッセージング インフラストラクチャ内のエンティティに送信されます。Having that pair of links in place, the request/response implementation is straightforward: a request is a message sent to an entity inside the messaging infrastructure that understands this pattern. その要求メッセージでは、properties セクションの reply-to フィールドが、応答の配信に使用されるリンクの target ID に設定されます。In that request-message, the reply-to field in the properties section is set to the target identifier for the link onto which to deliver the response. 要求を処理する側のエンティティは、その要求を処理した後、指定された reply-to ID と一致する target ID を持ったリンクを介して応答を配信します。The handling entity processes the request, and then delivers the reply over the link whose target identifier matches the indicated reply-to identifier.

当然このパターンにはクライアント コンテナーが必要です。また、応答の宛先としてクライアントが生成する ID は、すべてのクライアントを通じて一意で、なおかつセキュリティ上の理由から推測されにくいことが条件となります。The pattern obviously requires that the client container and the client-generated identifier for the reply destination are unique across all clients and, for security reasons, also difficult to predict.

管理プロトコルやそれと同じパターンを使用するすべてのプロトコルのメッセージ交換は、アプリケーション レベルで実行され、新たに AMQP プロトコル レベルのジェスチャは定義されていません。The message exchanges used for the management protocol and for all other protocols that use the same pattern happen at the application level; they do not define new AMQP protocol-level gestures. これは意図的な措置です。こうした拡張機能と仕様に準拠している AMQP 1.0 スタックの利点をアプリケーションがそのまま活かせるようになっています。That's intentional, so that applications can take immediate advantage of these extensions with compliant AMQP 1.0 stacks.

Service Bus には現在、管理仕様の核となる機能が実装されていませんが、管理仕様によって定義されている要求/応答パターンは、CBS (Claims Based Security) 機能および、以降のセクションで取り上げる高度な機能のほぼすべてで基礎となるものです。Service Bus does not currently implement any of the core features of the management specification, but the request/response pattern defined by the management specification is foundational for the claims-based-security feature and for nearly all of the advanced capabilities discussed in the following sections:

Claims-Based AuthorizationClaims-based authorization

AMQP Claims-Based-Authorization (CBS) 仕様草案は、管理仕様の要求/応答パターンをベースとし、フェデレーション方式のセキュリティ トークンを AMQP で使用するための一般的なモデルを規定しています。The AMQP Claims-Based-Authorization (CBS) specification draft builds on the management specification request/response pattern, and describes a generalized model for how to use federated security tokens with AMQP.

冒頭で説明した AMQP の既定のセキュリティ モデルは SASL をベースとしており、AMQP 接続ハンドシェイクと統合されています。The default security model of AMQP discussed in the introduction is based on SASL and integrates with the AMQP connection handshake. SASL を使用することの利点は、SASL に備わっている拡張可能なモデルです。そのモデルにあらかじめ定義されている一連のメカニズムを、SASL の形式に正しく対応した任意のプロトコルから利用することができます。Using SASL has the advantage that it provides an extensible model for which a set of mechanisms have been defined from which any protocol that formally leans on SASL can benefit. そうしたメカニズムの代表的な例としては、"PLAIN" (ユーザー名とパスワードを転送するための機構)、"EXTERNAL" (TLS レベルのセキュリティにバインドするための機構)、"ANONYMOUS" (明示的な認証/承認が存在しないことを示すための機構) のほか、認証/承認の資格情報やトークンを受け渡しするためのさまざまな機構が挙げられます。Among those mechanisms are “PLAIN” for transfer of usernames and passwords, “EXTERNAL” to bind to TLS-level security, “ANONYMOUS” to express the absence of explicit authentication/authorization, and a broad variety of additional mechanisms that allow passing authentication and/or authorization credentials or tokens.

AMQP への SASL の統合には、2 つの欠点があります。AMQP’s SASL integration has two drawbacks:

  • すべての資格情報とトークンの適用範囲が、対象となる接続に限定される。All credentials and tokens are scoped to the connection. メッセージング インフラストラクチャでは、エンティティごとに差別化されたアクセス制御を提供する必要がある場合があります。たとえばトークンのベアラーに、キュー A に対する送信を許可しつつ、キュー B への送信を禁止するケースを考えてみましょう。承認コンテキストは接続に固定されるため、単一の接続を使用しながら、キュー A とキュー B に異なるアクセス トークンを使用することはできません。A messaging infrastructure may want to provide differentiated access control on a per-entity basis; for example, allowing the bearer of a token to send to queue A but not to queue B. With the authorization context anchored on the connection, it’s not possible to use a single connection and yet use different access tokens for queue A and queue B.
  • 一般にアクセス トークンは有効期間が限られている。Access tokens are typically only valid for a limited time. ユーザーは、定期的にトークンを取得し直す必要があります。ユーザーのアクセス権が変更されている場合には、新しいトークンの発行を拒否する余地がトークンの発行者に与えられなければなりません。This validity requires the user to periodically reacquire tokens and provides an opportunity to the token issuer to refuse issuing a fresh token if the user’s access permissions have changed. AMQP の接続は、長時間にわたって持続する場合があります。AMQP connections may last for long periods of time. SASL モデルでは、トークンを設定する機会が接続時にしか用意されていません。つまり、メッセージング インフラストラクチャは、トークンの有効期限が切れたときにクライアントとの接続を切断するか、または、その間にアクセス権が失効されたクライアントとの接続をリスクを承知で維持するか、のどちらかを選ぶ必要があります。The SASL model only provides a chance to set a token at connection time, which means that the messaging infrastructure either has to disconnect the client when the token expires or it needs to accept the risk of allowing continued communication with a client who’s access rights may have been revoked in the interim.

Service Bus によって実装される AMQP CBS 仕様により、これらの問題の両方に対する洗練された回避策が有効になります。これによりクライアントは、各ノードにアクセス トークンを関連付け、メッセージ フローを中断することなく、期限切れ前にそれらのトークンを更新することができます。The AMQP CBS specification, implemented by Service Bus, enables an elegant workaround for both of those issues: It allows a client to associate access tokens with each node, and to update those tokens before they expire, without interrupting the message flow.

CBS には、メッセージング インフラストラクチャによって提供される $cbs という名前の仮想管理ノードが定義されています。CBS defines a virtual management node, named $cbs, to be provided by the messaging infrastructure. トークンの受理は、この管理ノードがメッセージング インフラストラクチャ内の他のノードに代わって行います。The management node accepts tokens on behalf of any other nodes in the messaging infrastructure.

このプロトコル ジェスチャは、管理仕様で規定されている要求/応答のやり取りです。The protocol gesture is a request/reply exchange as defined by the management specification. つまりクライアントは、 $cbs ノードとの間に 2 本のリンクを確立し、送信リンクで要求を渡した後、受信リンクで応答を待機します。That means the client establishes a pair of links with the $cbs node and then passes a request on the outbound link, and then waits for the response on the inbound link.

要求メッセージには、次のアプリケーション プロパティがあります。The request message has the following application properties:

キーKey 省略可能Optional 値の型Value Type 値の内容Value Contents
operationoperation いいえNo stringstring put-tokenput-token
typetype いいえNo stringstring 格納されるトークンの種類。The type of the token being put.
namename いいえNo stringstring 発行先 (トークンの適用先)。The "audience" to which the token applies.
expirationexpiration はいYes timestamptimestamp トークンの有効期限。The expiry time of the token.

トークンの関連付けの対象となるエンティティは、name プロパティによって識別されます。The name property identifies the entity with which the token shall be associated. Service Bus では、キュー (またはトピック/サブスクリプション) のパスになります。In Service Bus it's the path to the queue, or topic/subscription. トークンの種類は、type プロパティによって識別されます。The type property identifies the token type:

トークンの種類Token Type トークンの説明Token Description 本文の型Body Type メモNotes
amqp:jwtamqp:jwt JSON Web トークン (JWT)JSON Web Token (JWT) AMQP 値 (string)AMQP Value (string) まだ使用できません。Not yet available.
amqp:swtamqp:swt Simple Web Token (SWT)Simple Web Token (SWT) AMQP 値 (string)AMQP Value (string) AAD/ACS によって発行された SWT トークンでのみサポートされます。Only supported for SWT tokens issued by AAD/ACS
servicebus.windows.net:sastokenservicebus.windows.net:sastoken Service Bus SAS トークンService Bus SAS Token AMQP 値 (string)AMQP Value (string) -

トークンには、権限を与える作用があります。Tokens confer rights. Service Bus は、3 つの基本的な権限として、"Send" (送信を許可)、"Listen" (受信を許可)、"Manage" (エンティティの操作を許可) を認識します。Service Bus knows about three fundamental rights: "Send" enables sending, "Listen" enables receiving, and "Manage" enables manipulating entities. AAD/ACS によって明示的に発行された SWT トークンは、これらの権限を要求 (claim) として含んでいます。SWT tokens issued by AAD/ACS explicitly include those rights as claims. Service Bus の SAS トークンは、名前空間またはエンティティに対して構成されている規則を参照し、それらの規則が権限で構成されています。Service Bus SAS tokens refer to rules configured on the namespace or entity, and those rules are configured with rights. したがって、その規則に関連付けられているキーでトークンに署名すると、トークンが個別の権限を表すようになります。Signing the token with the key associated with that rule thus makes the token express the respective rights. エンティティには、put-token を使ってトークンが関連付けられます。接続クライアントは、このトークンの権限に従ってエンティティを操作することができます。The token associated with an entity using put-token permits the connected client to interact with the entity per the token rights. クライアントが "送信側" の役割を担うリンクには "Send" 権限が、"受信側" の役割を担うリンクには "Listen" 権限が必要となります。A link where the client takes on the sender role requires the "Send" right; taking on the receiver role requires the "Listen" right.

応答メッセージには、次の application-properties 値があります。The reply message has the following application-properties values

キーKey 省略可能Optional 値の型Value Type 値の内容Value Contents
status-codestatus-code いいえNo intint HTTP 応答コード [RFC2616]HTTP response code [RFC2616].
status-descriptionstatus-description はいYes stringstring ステータスの説明。Description of the status.

クライアントは、メッセージング インフラストラクチャ内の任意のエンティティに対し、put-token を繰り返し呼び出すことができます。The client can call put-token repeatedly and for any entity in the messaging infrastructure. トークンの有効範囲は現在のクライアントに限定され、現在の接続に固定されます。つまり、保持されているトークンは、接続が失われた時点でサーバーによって破棄されます。The tokens are scoped to the current client and anchored on the current connection, meaning the server drops any retained tokens when the connection drops.

Service Bus の現在の実装では、SASL の "ANONYMOUS" 方式との組み合わせでしか CBS を使用できません。The current Service Bus implementation only allows CBS in conjunction with the SASL method "ANONYMOUS." 常に SASL ハンドシェイクの前に、SSL/TLS 接続が存在していることが必要です。A SSL/TLS connection must always exist prior to the SASL handshake.

したがって、選択した AMQP 1.0 クライアントが ANONYMOUS のメカニズムをサポートしている必要があります。The ANONYMOUS mechanism must therefore be supported by the chosen AMQP 1.0 client. 匿名アクセスは、だれが接続を作成しているのかを Service Bus が関知しない状況下で、初回接続ハンドシェイク (初回セッションの作成を含む) が実行されることを意味します。Anonymous access means that the initial connection handshake, including creating of the initial session happens without Service Bus knowing who is creating the connection.

許可される操作は、接続とセッションが確立された後、 $cbs ノードにリンクを割り当て、put-token 要求を送信することだけです。Once the connection and session is established, attaching the links to the $cbs node and sending the put-token request are the only permitted operations. 接続が確立されてから 20 秒以内に、put-token 要求を使用して特定のエンティティ ノードに有効なトークンを正しく設定する必要があります。それに失敗すると、接続は Service Bus によって一方的に破棄されます。A valid token must be set successfully using a put-token request for some entity node within 20 seconds after the connection has been established, otherwise the connection is unilaterally dropped by Service Bus.

以後トークンの期限を追跡する役割は、クライアントが果たすこととなります。The client is subsequently responsible for keeping track of token expiration. トークンの有効期限が切れるとすぐ、個々のエンティティとの間でその接続上に形成されていたリンクはすべて Service Bus によって破棄されます。When a token expires, Service Bus promptly drops all links on the connection to the respective entity. 問題の発生を防ぐためにクライアントは随時、仮想 $cbs 管理ノードを介し、同じ put-token ジェスチャを使用して、ノードのトークンを新しいトークンに差し替えることができます。このとき、他のリンク上を流れるペイロード トラフィックの障害になることはありません。To prevent problem occurring, the client can replace the token for the node with a new one at any time through the virtual $cbs management node with the same put-token gesture, and without getting in the way of the payload traffic that flows on different links.

経由送信の機能Send-via functionality

経由送信 / 送信元の転送は、Service Bus が指定されたメッセージを別のエンティティ経由で宛先エンティティに転送できる機能です。Send-via / Transfer sender is a functionality that lets service bus forward a given message to a destination entity through another entity. これは、単一のトランザクション内の複数のエンティティにわたる操作を実行するために使用されます。This feature is used to perform operations across entities in a single transaction.

この機能により、送信元を作成して via-entity へのリンクを確立します。With this functionality, you create a sender and establish the link to the via-entity. リンクの確立中に、このリンクでのメッセージ/転送の実際の宛先を確立するために、追加の情報が渡されます。While establishing the link, additional information is passed to establish the true destination of the messages/transfers on this link. 接続に成功すると、以降はこのリンク上で送信されるすべてのメッセージは自動的に via-entity 経由で destination-entity に転送されます。Once the attach has been successful, all the messages sent on this link are automatically forwarded to the destination-entity through via-entity.

注:このリンクを確立する前に、via-entitydestination-entity の両方に対して認証が実行される必要があります。Note: Authentication has to be performed for both via-entity and destination-entity before establishing this link.

ClientClient Service BusService Bus
attach(attach(
name={link name},name={link name},
role=sender,role=sender,
source={client link ID},source={client link ID},
target= {via-entity} ,target={via-entity},
properties=map [(
com.microsoft:transfer-destination-address=
{destination-entity} )]
)
properties=map [(
com.microsoft:transfer-destination-address=
{destination-entity} )]
)
------>
<------ attach(attach(
name={link name},name={link name},
role=receiver,role=receiver,
source={client link ID},source={client link ID},
target={via-entity},target={via-entity},
properties=map [(properties=map [(
com.microsoft:transfer-destination-address=com.microsoft:transfer-destination-address=
{destination-entity} )] ){destination-entity} )] )

次の手順Next steps

AMQP の詳細については、次のリンクを参照してください。To learn more about AMQP, visit the following links: