AMQP 訊息頭

概述

Spring Integration AMQP 介面卡會自動對映所有 AMQP 屬性和訊息頭。(這是從 4.3 版本開始的變更 - 以前僅對映標準訊息頭)。預設情況下,這些屬性使用 DefaultAmqpHeaderMapper 在 Spring Integration MessageHeaders 之間來回複製。

您可以傳入自己的 AMQP 特定訊息頭對映器實現,因為介面卡支援透過屬性進行此操作。

AMQP MessageProperties 中的任何使用者定義訊息頭都會複製到 AMQP 訊息或從 AMQP 訊息複製,除非被 DefaultAmqpHeaderMapperrequestHeaderNamesreplyHeaderNames 屬性明確否定。預設情況下,對於出站對映器,不會對映任何 x-* 訊息頭。有關原因,請參閱本節後面出現的注意事項

要覆蓋預設設定並恢復到 4.3 版本之前的行為,請在屬性中使用 STANDARD_REQUEST_HEADERSSTANDARD_REPLY_HEADERS

對映使用者定義訊息頭時,值也可以包含簡單的萬用字元模式(例如 thing**thing)進行匹配。* 匹配所有訊息頭。

從 4.1 版本開始,AbstractHeaderMapperDefaultAmqpHeaderMapper 的超類)允許為 requestHeaderNamesreplyHeaderNames 屬性配置 NON_STANDARD_HEADERS 令牌(除了現有的 STANDARD_REQUEST_HEADERSSTANDARD_REPLY_HEADERS),以對映所有使用者定義的頭。

org.springframework.amqp.support.AmqpHeaders 類標識了 DefaultAmqpHeaderMapper 使用的預設訊息頭

  • amqp_appId

  • amqp_clusterId

  • amqp_contentEncoding

  • amqp_contentLength

  • content-type(參見 contentType 訊息頭

  • amqp_correlationId

  • amqp_delay

  • amqp_deliveryMode

  • amqp_deliveryTag

  • amqp_expiration

  • amqp_messageCount

  • amqp_messageId

  • amqp_receivedDelay

  • amqp_receivedDeliveryMode

  • amqp_receivedExchange

  • amqp_receivedRoutingKey

  • amqp_redelivered

  • amqp_replyTo

  • amqp_timestamp

  • amqp_type

  • amqp_userId

  • amqp_publishConfirm

  • amqp_publishConfirmNackCause

  • amqp_returnReplyCode

  • amqp_returnReplyText

  • amqp_returnExchange

  • amqp_returnRoutingKey

  • amqp_channel

  • amqp_consumerTag

  • amqp_consumerQueue

如本節前面所述,使用 * 訊息頭對映模式是複製所有訊息頭的常用方法。然而,這可能會產生一些意外的副作用,因為某些 RabbitMQ 專有屬性/訊息頭也會被複制。例如,當您使用聯合交換器 (federation) 時,接收到的訊息可能有一個名為 x-received-from 的屬性,其中包含傳送訊息的節點。如果您在入站閘道器上使用萬用字元 * 進行請求和回覆訊息頭對映,此訊息頭會被複制,這可能會導致聯合出現問題。此回覆訊息可能會被聯合回傳送代理,傳送代理可能會認為訊息正在迴圈,並因此靜默丟棄它。如果您希望使用萬用字元訊息頭對映的便利性,您可能需要在下游流中過濾掉一些訊息頭。例如,為了避免將 x-received-from 訊息頭複製回回復,您可以在將回復發送到 AMQP 入站閘道器之前使用 <int:header-filter …​ header-names="x-received-from">。或者,您可以明確列出您實際希望對映的屬性,而不是使用萬用字元。出於這些原因,對於入站訊息,對映器(預設情況下)不對映任何 x-* 訊息頭。它也不將 deliveryMode 對映到 amqp_deliveryMode 訊息頭,以避免該訊息頭從入站訊息傳播到出站訊息。相反,此訊息頭被對映到 amqp_receivedDeliveryMode,該訊息頭在輸出時不會被對映。

從 4.3 版本開始,訊息頭對映中的模式可以透過在模式前加上 ! 來否定。被否定的模式具有優先順序,因此像 STANDARD_REQUEST_HEADERS,thing1,ba*,!thing2,!thing3,qux,!thing1 這樣的列表不會對映 thing1(也不會對映 thing2thing3)。標準訊息頭以及 badqux 會被對映。否定技術對於例如在接收器下游以不同方式執行 JSON 反序列化邏輯時不對映 JSON 型別訊息頭非常有用。為此,應為入站通道介面卡/閘道器的訊息頭對映器配置 !json_* 模式。

如果您有一個以 ! 開頭的使用者定義訊息頭,並且您確實希望對映它,則需要使用 \ 進行轉義,如下所示:STANDARD_REQUEST_HEADERS,\!myBangHeader。名為 !myBangHeader 的訊息頭現在被映射了。
從 5.1 版本開始,如果出站訊息上不存在相應的 amqp_messageIdamqp_timestamp 訊息頭,DefaultAmqpHeaderMapper 將回退到分別將 MessageHeaders.IDMessageHeaders.TIMESTAMP 對映到 MessageProperties.messageIdMessageProperties.timestamp。入站屬性將像以前一樣對映到 amqp_* 訊息頭。在訊息消費者使用有狀態重試時,填充 messageId 屬性非常有用。

contentType 訊息頭

與其他訊息頭不同,AmqpHeaders.CONTENT_TYPE 沒有字首 amqp_;這使得 contentType 訊息頭可以在不同的技術之間透明傳遞。例如,傳送到 RabbitMQ 佇列的入站 HTTP 訊息。

contentType 訊息頭被對映到 Spring AMQP 的 MessageProperties.contentType 屬性,然後該屬性被對映到 RabbitMQ 的 content_type 屬性。

在 5.1 版本之前,此訊息頭也被對映為 MessageProperties.headers map 中的一個條目;這是不正確的,而且,由於底層的 Spring AMQP 訊息轉換器可能改變了內容型別,該值可能是錯誤的。這種變化會反映在一等(first-class)的 content_type 屬性中,但不會反映在 RabbitMQ headers map 中。入站對映會忽略 headers map 中的值。contentType 不再對映到 headers map 中的一個條目。