訊息歷史

訊息架構的關鍵優勢在於鬆散耦合,參與元件彼此之間沒有任何感知。僅憑這一點就使得應用程式非常靈活,允許你在不影響流程其餘部分的情況下更改元件、更改訊息路由、更改訊息消費方式(輪詢與事件驅動),等等。然而,當出現問題時,這種不顯眼的架構風格可能會變得困難。在除錯時,你可能希望儘可能多地獲取關於訊息的資訊(其來源、遍歷的通道以及其他詳細資訊)。

訊息歷史是一種模式,透過提供一種選項來幫助你維護訊息路徑的某種程度的感知,無論是出於除錯目的還是為了維護審計跟蹤。Spring Integration 提供了一種簡單的方法來配置你的訊息流以維護訊息歷史,即透過向訊息新增一個頭並在訊息每次透過被跟蹤的元件時更新該頭。

訊息歷史配置

要啟用訊息歷史,你只需在配置中定義 message-history 元素(或 @EnableMessageHistory),如下例所示

  • Java

  • XML

@Configuration
@EnableIntegration
@EnableMessageHistory
<int:message-history/>

現在,每個命名的元件(定義了“id”)都會被跟蹤。框架會在你的訊息中設定“history”頭。它的值是一個 List<Properties>

考慮以下配置示例

  • Java

  • XML

@MessagingGateway(defaultRequestChannel = "bridgeInChannel")
public interface SampleGateway {
   ...
}

@Bean
@Transformer(inputChannel = "enricherChannel", outputChannel="filterChannel")
HeaderEnricher sampleEnricher() {
    HeaderEnricher enricher =
           new HeaderEnricher(Collections.singletonMap("baz", new StaticHeaderValueMessageProcessor("baz")));
    return enricher;
}
<int:gateway id="sampleGateway"
    service-interface="org.springframework.integration.history.sample.SampleGateway"
    default-request-channel="bridgeInChannel"/>

<int:header-enricher id="sampleEnricher" input-channel="enricherChannel" output-channel="filterChannel">
    <int:header name="baz" value="baz"/>
</int:header-enricher>

前面的配置產生一個簡單的訊息歷史結構,輸出類似於以下內容

[{name=sampleGateway, type=gateway, timestamp=1283281668091},
 {name=sampleEnricher, type=header-enricher, timestamp=1283281668094}]

要訪問訊息歷史,你只需訪問 MessageHistory 頭即可。以下示例展示瞭如何操作

Iterator<Properties> historyIterator =
    message.getHeaders().get(MessageHistory.HEADER_NAME, MessageHistory.class).iterator();
assertTrue(historyIterator.hasNext());
Properties gatewayHistory = historyIterator.next();
assertEquals("sampleGateway", gatewayHistory.get("name"));
assertTrue(historyIterator.hasNext());
Properties chainHistory = historyIterator.next();
assertEquals("sampleChain", chainHistory.get("name"));

你可能不想跟蹤所有元件。要將歷史記錄限制為基於其名稱的特定元件,你可以提供 tracked-components 屬性並指定一個逗號分隔的元件名稱和模式列表,這些名稱和模式與你想跟蹤的元件匹配。以下示例展示瞭如何操作

  • Java

  • XML

@Configuration
@EnableIntegration
@EnableMessageHistory("*Gateway", "sample*", "aName")
<int:message-history tracked-components="*Gateway, sample*, aName"/>

在前面的示例中,訊息歷史僅為名稱以“Gateway”結尾、以“sample”開頭或名稱恰好匹配“aName”的元件維護。

此外,MessageHistoryConfigurer bean 現在透過 IntegrationMBeanExporter 暴露為 JMX MBean(參見MBean Exporter),允許你在執行時更改模式。但是請注意,必須停止該 bean(關閉訊息歷史)才能更改模式。此功能可能有助於臨時開啟歷史記錄以分析系統。MBean 的物件名稱是 <域名>:名稱=訊息歷史配置器,型別=訊息歷史配置器

應用程式上下文中只能宣告一個 @EnableMessageHistory(或 <message-history/>),作為元件跟蹤配置的單一來源。不要使用通用的 bean 定義來定義 MessageHistoryConfigurer
在 6.3 版本之前,訊息歷史頭是不可變的(你無法重寫歷史):每個獨立的跟蹤不僅建立新的 MessageHistory 例項,而且建立一個全新的訊息副本。現在它以僅追加模式工作:第一次跟蹤建立一個帶有新的 MessageHistory 容器的新訊息。所有其餘的 MessageHistory.write() 呼叫都會向現有頭新增新條目 - 並且不會建立新訊息。這顯著提升了應用程式效能。框架中,同一訊息可以傳送給多個消費者(PublishSubscribeChannelAbstractMessageRouterWireTap 等),或者拆分器基於輸入訊息生成多個輸出的所有元件,現在都將現有 MessageHistory 頭克隆到這些新訊息中。對於框架範圍之外的任何其他多生成用例,建議使用 AbstractIntegrationMessageBuilder.cloneMessageHistoryIfAny() API,以確保並行的下游子流貢獻各自的訊息歷史痕跡。