消息传递体系结构的主要优点是松散耦合,因此参与的组件不会保持对彼此的任何感知。 仅这一事实就使应用程序非常灵活,允许您在不影响流的其余部分的情况下更改组件、更改消息传递路由、更改消息使用样式(轮询与事件驱动)等等。 然而,当出现问题时,这种不起眼的架构风格可能会很困难。 在调试时,您可能希望获得尽可能多的有关消息的信息 (其来源、它遍历的通道和其他详细信息)。spring-doc.cn

Message History 是一种有用的模式,它为您提供了一个选项来保持对消息路径的某种程度的感知,用于调试目的或维护审计跟踪。 Spring 集成提供了一种简单的方法来配置消息流以维护消息历史记录,方法是向消息添加 Headers 并在每次消息通过跟踪组件时更新该 Header。spring-doc.cn

消息历史记录配置

要启用消息历史记录,您只需在配置中定义元素 (或 ),如以下示例所示:message-history@EnableMessageHistoryspring-doc.cn

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

现在,每个命名组件(定义了 'id')都会被跟踪。 框架会在您的消息中设置 'history' 标头。 其值 a .List<Properties>spring-doc.cn

请考虑以下配置示例:spring-doc.cn

@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>

前面的配置生成一个简单的消息历史记录结构,其输出类似于以下内容:spring-doc.cn

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

要访问消息历史记录,您只需访问标头。 以下示例显示了如何执行此操作:MessageHistoryspring-doc.cn

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-componentsspring-doc.cn

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

在前面的示例中,仅维护以“Gateway”结尾、以“sample”开头或与名称“aName”完全匹配的组件的消息历史记录。spring-doc.cn

此外,Bean 现在由 (请参阅 MBean Exporter) 作为 JMX MBean 公开,允许您在运行时更改模式。 但是请注意,必须停止 Bean (关闭消息历史记录) 才能更改模式。 此功能对于临时打开历史记录以分析系统可能很有用。 MBean 的对象名称为 。MessageHistoryConfigurerIntegrationMBeanExporter<domain>:name=messageHistoryConfigurer,type=MessageHistoryConfigurerspring-doc.cn

在应用程序上下文中,只有一个 (或 ) 必须声明为组件跟踪配置的单一源。 不要对 .@EnableMessageHistory<message-history/>MessageHistoryConfigurer
在 6.3 版本之前,消息历史记录标头是不可变的(您不能重写历史记录):每个跟踪不仅创建了 的新实例,而且创建了一个全新的消息副本。 现在,它在 append-only 模式下工作:第一个轨道使用新容器创建新消息。 所有 rest 调用都会向现有 header 添加新条目 - 并且不会创建新消息。 这显著提高了应用程序性能。 框架中的所有组件,其中可以将同一消息发送给多个使用者(、 等),或者 splitter 根据输入消息生成多个输出,现在正在将现有标头克隆到这些新消息中。 对于框架范围之外的任何其他多生产用例,建议使用 API 来确保并行下游子流提供自己的消息历史记录跟踪。MessageHistoryMessageHistoryMessageHistory.write()PublishSubscribeChannelAbstractMessageRouterWireTapMessageHistoryAbstractIntegrationMessageBuilder.cloneMessageHistoryIfAny()
在应用程序上下文中,只有一个 (或 ) 必须声明为组件跟踪配置的单一源。 不要对 .@EnableMessageHistory<message-history/>MessageHistoryConfigurer
在 6.3 版本之前,消息历史记录标头是不可变的(您不能重写历史记录):每个跟踪不仅创建了 的新实例,而且创建了一个全新的消息副本。 现在,它在 append-only 模式下工作:第一个轨道使用新容器创建新消息。 所有 rest 调用都会向现有 header 添加新条目 - 并且不会创建新消息。 这显著提高了应用程序性能。 框架中的所有组件,其中可以将同一消息发送给多个使用者(、 等),或者 splitter 根据输入消息生成多个输出,现在正在将现有标头克隆到这些新消息中。 对于框架范围之外的任何其他多生产用例,建议使用 API 来确保并行下游子流提供自己的消息历史记录跟踪。MessageHistoryMessageHistoryMessageHistory.write()PublishSubscribeChannelAbstractMessageRouterWireTapMessageHistoryAbstractIntegrationMessageBuilder.cloneMessageHistoryIfAny()