AMQP の抽象化
Spring AMQP は、2 つのモジュール (それぞれ配布版では JAR で表されます) spring-amqp と spring-rabbit で構成されています。'spring-amqp' モジュールには、org.springframework.amqp.core パッケージが含まれています。そのパッケージには、コア AMQP「モデル」を表すクラスが含まれています。私たちの目的は、特定の AMQP ブローカー実装やクライアントライブラリに依存しない汎用抽象化を提供することです。エンドユーザーコードは抽象化レイヤーのみに対して開発できるため、ベンダー実装間での移植性が向上します。これらの抽象化は、'spring-rabbit' などのブローカー固有のモジュールによって実装されます。現在は RabbitMQ 実装のみです。ただし、抽象化は RabbitMQ に加えて Apache Qpid を使用して .NET で検証されています。AMQP はプロトコルレベルで動作するため、原則として、同じプロトコルバージョンをサポートする任意のブローカーで RabbitMQ クライアントを使用できますが、現時点では他のブローカーはテストしていません。
この概要は、AMQP 仕様の基本をすでに理解していることを前提としています。そうでない場合は、その他のリソースにリストされているリソースを参照してください。
Message
0-9-1 AMQP 仕様は、Message クラスまたはインターフェースを定義していません。代わりに、basicPublish() などの操作を実行する場合、コンテンツはバイト配列引数として渡され、追加のプロパティは別の引数として渡されます。Spring AMQP は、より一般的な AMQP ドメインモデル表現の一部として Message クラスを定義します。Message クラスの目的は、本体とプロパティを 1 つのインスタンス内にカプセル化して、API をよりシンプルにすることです。次の例は、Message クラス定義を示しています。
public class Message {
private final MessageProperties messageProperties;
private final byte[] body;
public Message(byte[] body, MessageProperties messageProperties) {
this.body = body;
this.messageProperties = messageProperties;
}
public byte[] getBody() {
return this.body;
}
public MessageProperties getMessageProperties() {
return this.messageProperties;
}
}MessageProperties インターフェースは、"messageId"、"timestamp"、"contentType" など、いくつかの共通プロパティを定義します。また、setHeader(String key, Object value) メソッドを呼び出すことで、ユーザー定義の「ヘッダー」を使用してこれらのプロパティを継承することもできます。
バージョン 1.5.7、1.6.11、1.7.4、2.0.0 以降では、メッセージ本文が直列化された Serializable java オブジェクトである場合、toString() 操作 (ログメッセージなど) を実行するときに、(デフォルトで) デシリアライズされなくなりました。これは、安全でないデシリアライズを防ぐためです。デフォルトでは、java.util および java.lang クラスのみが逆直列化されます。以前の動作に戻すには、Message.addAllowedListPatterns(…) を呼び出して、許容されるクラス / パッケージパターンを追加できます。com.something.*, *.MyClass などの単純な * ワイルドカードがサポートされています。デシリアライズできない本体は、ログメッセージで byte[<size>] で表されます。 |
交換
Exchange インターフェースは、メッセージプロデューサーの送信先である AMQP 交換を表します。ブローカーの仮想ホスト内の各 Exchange には、一意の名前とその他のいくつかのプロパティがあります。次の例は、Exchange インターフェースを示しています。
public interface Exchange extends Declarable {
String getName();
String getType();
boolean isDurable();
boolean isAutoDelete();
Map<String, Object> getArguments();
} ご覧のとおり、Exchange には ExchangeTypes で定義された定数によって表される「型」もあります。基本型は次のとおりです。direct、topic、fanout、headers。コアパッケージには、これらの各型の Exchange インターフェースの実装があります。キューへのバインディングを処理する方法に関して、これらの Exchange 型間で動作が異なります。例: Direct 交換では、固定ルーティングキー (多くの場合、キューの名前) によってキューをバインドできます。Topic 交換は、それぞれ「正確に 1 つ」および「0 以上」を表す "*" および "#" ワイルドカードを含む可能性のあるルーティングパターンでバインディングをサポートします。Fanout 交換は、ルーティングキーを考慮せずに、それにバインドされているすべてのキューに発行します。これらおよびその他の Exchange 型の詳細については、AMQP 交換 (英語) を参照してください。
バージョン 3.2 以降、アプリケーション構成フェーズでの利便性のために、ConsistentHashExchange 型が導入されました。交換型に x-consistent-hash などのオプションが提供されます。hash-header または hash-property 交換定義引数を構成できます。ブローカーで、それぞれの RabbitMQ rabbitmq_consistent_hash_exchange プラグインを有効にする必要があります。一貫性のあるハッシュ交換の目的、ロジック、動作の詳細については、公式の RabbitMQ ドキュメント [GitHub] (英語) を参照してください。
AMQP 仕様では、ブローカーが名前のない「デフォルト」の直接交換を提供することも必要です。宣言されたすべてのキューは、その名前をルーティングキーとしてデフォルトの Exchange にバインドされます。AmqpTemplate の Spring AMQP 内でのデフォルトの Exchange の使用箇所について詳しく知ることができます。 |
キュー
Queue クラスは、メッセージコンシューマーがメッセージを受信するコンポーネントを表します。さまざまな Exchange クラスと同様に、私たちの実装は、このコア AMQP 型の抽象表現を意図しています。次のリストは、Queue クラスを示しています。
public class Queue {
private final String name;
private final boolean durable;
private final boolean exclusive;
private final boolean autoDelete;
/**
* The queue is durable, non-exclusive and non auto-delete.
*
* @param name the name of the queue.
*/
public Queue(String name) {
this(name, true, false, false);
}
// Getters and Setters omitted for brevity
}コンストラクターがキュー名を受け取ることに注意してください。実装によっては、管理テンプレートが一意の名前のキューを生成するメソッドを提供する場合があります。このようなキューは、「返信先」アドレスやその他の一時的な状況で役立ちます。そのため、自動生成されたキューの 'exclusive' プロパティと 'autoDelete' プロパティは両方とも 'true' に設定されます。
| 名前空間サポートを使用したキューの宣言 (キュー引数を含む) については、ブローカーの構成のキューに関するセクションを参照してください。 |
バインディング
プロデューサーがエクスチェンジに送信し、コンシューマーがキューから受信する場合、キューをエクスチェンジに接続するバインディングは、メッセージングを介してこれらのプロデューサーとコンシューマーを接続するために重要です。Spring AMQP では、これらの接続を表す Binding クラスを定義します。このセクションでは、キューをエクスチェンジにバインドするための基本的なオプションについて説明します。
次の例に示すように、「流れるような API」スタイルを容易にするために BindingBuilder を提供します。
Queue queue = ...;
// bind a queue to a DirectExchange with a fixed routing key
Binding directBinding = BindingBuilder.bind(queue).to(new DirectExchange("someDirectExchange")).with("foo.bar");
// bind a queue to a TopicExchange with a routing pattern
Binding topicBinding = BindingBuilder.bind(queue).to(new TopicExchange("someTopicExchange")).with("foo.*");
// bind a queue to a FanoutExchange with no routing key
Binding fanoutBinding = BindingBuilder.bind(queue).to(new FanoutExchange("someFanoutExchange")); わかりやすくするために、前の例では BindingBuilder クラスを示していますが、このスタイルは、'bind()' メソッドの静的インポートを使用する場合にうまく機能します。 |
Binding クラスのインスタンスは、接続に関するデータのみを保持します。つまり、「アクティブな」コンポーネントではありません。ただし、後でブローカーの構成で説明するように、AmqpAdmin クラスは Binding インスタンスを使用して、ブローカーでバインディングアクションを実際にトリガーできます。また、同じセクションでわかるように、@Configuration クラス内で Spring の @Bean アノテーションを使用して Binding インスタンスを定義できます。AMQP 関連の Bean 定義を生成するためのアプローチをさらに簡素化し、アプリケーションの起動時に AMQP ブローカーですべてが宣言されるように、キュー、交換、バインディングを認識する便利な基本クラスもあります。
AmqpTemplate もコアパッケージ内で定義されています。実際の AMQP メッセージングに関与する主要なコンポーネントの 1 つとして、個別のセクションで詳しく説明します (AmqpTemplate を参照)。