AMQP 抽象
Spring AMQP 由兩個模組組成(每個模組在發行版中都由一個 JAR 表示):spring-amqp 和 spring-rabbit。'spring-amqp' 模組包含 org.springframework.amqp.core 包。在該包中,您可以找到代表核心 AMQP “模型” 的類。我們的目的是提供不依賴於任何特定 AMQP 代理實現或客戶端庫的通用抽象。由於終端使用者程式碼可以僅針對抽象層進行開發,因此在不同供應商實現之間可以更具可移植性。然後,這些抽象由特定於代理的模組實現,例如 'spring-rabbit'。目前只有 RabbitMQ 的實現。但是,除了 RabbitMQ 之外,這些抽象也已在 .NET 中使用 Apache Qpid 進行了驗證。由於 AMQP 在協議級別執行,原則上,您可以將 RabbitMQ 客戶端與任何支援相同協議版本的代理一起使用,但我們目前不測試任何其他代理。
本概述假設您已熟悉 AMQP 規範的基礎知識。如果不是,請檢視其他資源中列出的資源
Message
0-9-1 AMQP 規範沒有定義 Message 類或介面。相反,當執行諸如 basicPublish() 等操作時,內容作為位元組陣列引數傳遞,附加屬性作為單獨的引數傳遞。Spring AMQP 定義了一個 Message 類,作為更通用的 AMQP 領域模型表示的一部分。Message 類的目的是將正文和屬性封裝在一個例項中,從而使 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) 方法,使用使用者定義的“headers”來擴充套件這些屬性。
從版本 1.5.7、1.6.11、1.7.4 和 2.0.0 開始,如果訊息正文是序列化的 Serializable Java 物件,則在執行 toString() 操作(例如在日誌訊息中)時,預設情況下不再對其進行反序列化。這是為了防止不安全的 deserialization。預設情況下,只反序列化 java.util 和 java.lang 類。要恢復以前的行為,您可以透過呼叫 Message.addAllowedListPatterns(…) 新增允許的類/包模式。支援簡單的 * 萬用字元,例如 com.something.*, *.MyClass。無法反序列化的正文在日誌訊息中表示為 byte[<size>]。 |
Exchange
Exchange 介面表示一個 AMQP 交換機,訊息生產者將訊息傳送到該交換機。代理的虛擬主機中的每個交換機都有一個唯一的名稱以及一些其他屬性。以下示例顯示了 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 交換機支援包含 '*' 和 '#' 萬用字元的路由模式繫結,分別表示“恰好一個”和“零個或多個”。Fanout 交換機將訊息釋出到所有繫結到它的佇列,而不考慮任何路由鍵。有關這些以及其他交換機型別的更多資訊,請參閱 AMQP 交換機。
從 3.2 版本開始,引入了 ConsistentHashExchange 型別,以方便應用程式配置階段。它提供了諸如 x-consistent-hash 等選項作為交換機型別。允許配置 hash-header 或 hash-property 交換機定義引數。必須在代理上啟用相應的 RabbitMQ rabbitmq_consistent_hash_exchange 外掛。有關一致雜湊交換機的目的、邏輯和行為的更多資訊,請參見 RabbitMQ 官方文件。
AMQP 規範還要求任何代理都提供一個沒有名稱的“預設”直連交換機。所有宣告的佇列都以其名稱作為路由鍵繫結到該預設 Exchange。您可以在AmqpTemplate中瞭解更多關於預設 Exchange 在 Spring AMQP 中的用法。 |
Queue
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
}
請注意,建構函式接受佇列名稱。根據實現的不同,管理模板可能會提供用於生成唯一命名佇列的方法。此類佇列可用作“reply-to”地址或在其他臨時情況下使用。因此,自動生成的佇列的“exclusive”和“autoDelete”屬性都將設定為“true”。
| 有關使用名稱空間支援(包括佇列引數)宣告佇列的資訊,請參閱配置代理中關於佇列的部分。 |
Binding
鑑於生產者傳送到交換機,消費者從佇列接收,連線佇列與交換機的繫結對於透過訊息傳遞連線這些生產者和消費者至關重要。在 Spring AMQP 中,我們定義了一個 Binding 類來表示這些連線。本節回顧了將佇列繫結到交換機的基本選項。
我們提供了一個 BindingBuilder 以方便“流暢 API”樣式,如下例所示
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 例項來實際觸發代理上的繫結操作。此外,正如您在該同一部分中看到的,您可以使用 Spring 的 @Bean 註解在 @Configuration 類中定義 Binding 例項。還有一個方便的基類,它進一步簡化了生成 AMQP 相關 bean 定義的方法,並識別佇列、交換機和繫結,以便在應用程式啟動時在 AMQP 代理上宣告它們。
AmqpTemplate 也定義在核心包中。作為涉及實際 AMQP 訊息傳遞的主要元件之一,它在自己的部分中進行了詳細討論(參見AmqpTemplate)。