认领检查

在前面的章节中,我们介绍了几个内容丰富器组件,它们可以帮助您处理消息缺少数据的情况。 我们还讨论了内容过滤,它允许您从消息中删除数据项。 然而,有时我们希望临时隐藏数据。 例如,在分布式系统中,我们可能会收到一个带有非常大有效载荷的消息。 一些间歇性的消息处理步骤可能不需要访问此有效载荷,有些可能只需要访问某些头部,因此,通过每个处理步骤携带大型消息有效载荷可能会导致性能下降,可能产生安全风险,并可能使调试更加困难。 库中存储(或认领检查)模式描述了一种机制,它允许您将数据存储在一个众所周知的位置,同时只维护一个指向该数据位置的指针(认领检查)。 您可以将该指针作为新消息的有效载荷传递,从而让消息流中的任何组件在需要时立即获取实际数据。 这种方法与挂号信流程非常相似,您在邮箱中收到一张认领检查单,然后必须去邮局认领您的实际包裹。 这与航班后或酒店中的行李认领也是相同的想法。 Spring Integration 提供了两种类型的认领检查转换器:

  • 传入认领检查转换器

  • 传出认领检查转换器

提供了方便的基于命名空间的机制来配置它们。

传入认领检查转换器

传入认领检查转换器通过将其存储在其 message-store 属性标识的消息存储中来转换传入消息。 以下示例定义了一个传入认领检查转换器:

<int:claim-check-in id="checkin"
        input-channel="checkinChannel"
        message-store="testMessageStore"
        output-channel="output"/>

在上述配置中,在 input-channel 上收到的消息被持久化到由 message-store 属性标识的消息存储中,并用生成的 ID 建立索引。 该 ID 是该消息的认领检查。 该认领检查也成为发送到 output-channel 的新(转换后的)消息的有效载荷。

现在,假设在某个时候您确实需要访问实际消息。 您可以手动访问消息存储并获取消息内容,或者您可以使用相同的方法(创建转换器),只是现在您通过使用传出认领检查转换器将认领检查转换为实际消息。

以下列表概述了传入认领检查转换器的所有可用参数:

<int:claim-check-in auto-startup="true"             [id="CO1-1"]1
                    id=""                           [id="CO1-2"]2
                    input-channel=""                [id="CO1-3"]3
                    message-store="messageStore"    [id="CO1-4"]4
                    order=""                        [id="CO1-5"]5
                    output-channel=""               [id="CO1-6"]6
                    send-timeout="">                [id="CO1-7"]7
    <int:poller></int:poller>                       [id="CO1-8"]8
</int:claim-check-in>
 <1>  生命周期属性,表示此组件是否应在应用程序上下文启动期间启动。
它默认为 `true`。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  标识底层 bean 定义 (`MessageTransformingHandler`) 的 ID。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  此端点的接收消息通道。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  对要由该认领检查转换器使用的 `MessageStore` 的引用。
如果未指定,则默认引用名为 `messageStore` 的 bean。
可选。
 <1>  当此端点作为订阅者连接到通道时,指定调用的顺序。
当该通道使用 `failover` 调度策略时,这尤其相关。
当此端点本身是带有队列的通道的轮询消费者时,它没有效果。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  标识消息在此端点处理后发送到的消息通道。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  指定发送回复消息到输出通道时等待的最长时间(以毫秒为单位)。
默认为 `30` 秒。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  定义一个轮询器。
此元素在 `Chain` 元素内不可用。
可选。

传出认领检查转换器

传出认领检查转换器允许您将带有认领检查有效载荷的消息转换为带有原始内容作为其有效载荷的消息。

<int:claim-check-out id="checkout"
        input-channel="checkoutChannel"
        message-store="testMessageStore"
        output-channel="output"/>

在上述配置中,在 input-channel 上收到的消息应将其认领检查作为其有效载荷。 传出认领检查转换器通过查询消息存储中由提供的认领检查标识的消息,将其转换为带有原始有效载荷的消息。 然后,它将新取出的消息发送到 output-channel

以下列表概述了传出认领检查转换器的所有可用参数:

<int:claim-check-out auto-startup="true"             [id="CO2-1"]1
                     id=""                           [id="CO2-2"]2
                     input-channel=""                [id="CO2-3"]3
                     message-store="messageStore"    [id="CO2-4"]4
                     order=""                        [id="CO2-5"]5
                     output-channel=""               [id="CO2-6"]6
                     remove-message="false"          [id="CO2-7"]7
                     send-timeout="">                [id="CO2-8"]8
    <int:poller></int:poller>                        [id="CO2-9"]9
</int:claim-check-out>
 <1>  生命周期属性,表示此组件是否应在应用程序上下文启动期间启动。
它默认为 `true`。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  标识底层 bean 定义 (`MessageTransformingHandler`) 的 ID。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  此端点的接收消息通道。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  对要由该认领检查转换器使用的 `MessageStore` 的引用。
如果未指定,则默认引用名为 `messageStore` 的 bean。
可选。
 <1>  当此端点作为订阅者连接到通道时,指定调用的顺序。
当该通道使用 `failover` 调度策略时,这尤其相关。
当此端点本身是带有队列的通道的轮询消费者时,它没有效果。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  标识消息在此端点处理后发送到的消息通道。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  如果设置为 `true`,则此转换器会从 `MessageStore` 中删除消息。
当消息只能 "`认领`" 一次时,此设置很有用。
它默认为 `false`。
可选。
 <1>  指定发送回复消息到输出通道时等待的最长时间(以毫秒为单位)。
它默认为 `30` 秒。
此属性在 `Chain` 元素内不可用。
可选。
 <1>  定义一个轮询器。
此元素在 `Chain` 元素内不可用。
可选。

仅认领一次

有时,特定消息必须只能认领一次。 打个比方,考虑处理飞机行李的过程。 您在出发时办理行李托运,在抵达时认领行李。 一旦行李被认领,除非再次办理托运,否则无法再次认领。 为了适应这种情况,我们在 claim-check-out 转换器上引入了一个 remove-message 布尔属性。 此属性默认为 false。 但是,如果设置为 true,则已认领的消息将从 MessageStore 中删除,以便无法再次认领。

此功能对存储空间有影响,尤其是在基于内存 MapSimpleMessageStore 的情况下,未能删除消息最终可能导致 OutOfMemoryException。 因此,如果您不期望进行多次认领,我们建议您将 remove-message 属性的值设置为 true。 以下示例展示了如何使用 remove-message 属性:

<int:claim-check-out id="checkout"
        input-channel="checkoutChannel"
        message-store="testMessageStore"
        output-channel="output"
        remove-message="true"/>

关于消息存储的说明

尽管我们很少关心认领检查的细节(只要它们有效),但您应该知道 Spring Integration 中实际认领检查(指针)的当前实现使用 UUID 来确保唯一性。

org.springframework.integration.store.MessageStore 是用于存储和检索消息的策略接口。 Spring Integration 提供了它的两个方便的实现:

  • SimpleMessageStore:基于内存 Map 的实现(默认,适用于测试)

  • JdbcMessageStore:使用 JDBC 关系数据库的实现